[英]Select first and last record of each group
我需要返回每组集合的第一条和最后一条记录。
数据:
Code Close Time
USD 146116 2022-04-03 04:00:00.00 +00:00
EUR 241789 2022-03-27 17:00:00.00 +00:00
EUR 241807 2022-03-27 08:00:00.00 +00:00
USD 141800 2022-03-27 08:00:00.00 +00:00
USD 140809 2022-03-27 07:00:00.00 +00:00
T-SQL:
SELECT
[Code]
,DATEADD(dd, 0, DATEDIFF(dd, 0, [Time]))
,FIRST_VALUE([Close]) OVER (ORDER BY [Time] ASC) AS [Open] -- Column 'Time' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
,MAX([Close]) AS [High]
,MIN([Close]) AS [Low]
,LAST_VALUE([Close]) OVER (ORDER BY [Time] ASC) AS [Close] -- Column 'Time' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
FROM [CurrencyIntradayHistories]
GROUP BY [Code],
DATEADD(dd, 0, DATEDIFF(dd, 0, [Time]))
ORDER BY [Time] ASC
期望的结果:
Code Open High Low Close Time
EUR 241807 241807 241789 241789 2022-03-27
USD 140809 141800 140809 141800 2022-03-27
USD 146116 146116 146116 146116 2022-04-03
你不能在这里直接使用FIRST_VALUE
,因为它是一个 window function,而不是聚合 function。
您需要将它嵌入到子查询/派生表中并对其使用聚合。
此外,它需要一个PARTITION BY
子句,以及ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
SELECT
cih.Code
,cih.Date
,MIN(cih.OpenPerDay) AS [Open]
,MAX(cih.[Close]) AS High
,MIN(cih.[Close]) AS Low
,MIN(cih.ClosePerDay) AS [Close]
FROM (
SELECT
*
,CAST(cih.Time AS date) AS Date
,FIRST_VALUE(cih.[Close]) OVER (PARTITION BY cih.Code, CAST(cih.Time AS date)
ORDER BY cih.Time ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS OpenPerDay
,LAST_VALUE(cih.[Close]) OVER (PARTITION BY cih.Code, CAST(cih.Time AS date)
ORDER BY cih.Time ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS ClosePerDay
FROM CurrencyIntradayHistories cih
) cih
GROUP BY
cih.Code,
cih.Date
ORDER BY
cih.Date;
一个稍微更有效的版本使用ROW_NUMBER
和LEAD
来查找开始和结束行。
SELECT
cih.Code
,cih.Date
,MIN(CASE WHEN cih.rn = 1 THEN cih.[Close] END) AS [Open]
,MAX(cih.[Close]) AS High
,MIN(cih.[Close]) AS Low
,MIN(CASE WHEN cih.NextClose IS NULL THEN cih.[Close] END) AS [Close]
FROM (
SELECT
*
,CAST(cih.Time AS date) AS Date
,ROW_NUMBER() OVER (PARTITION BY cih.Code, CAST(cih.Time AS date) ORDER BY cih.Time) AS rn
,LEAD(cih.[Close]) OVER (PARTITION BY cih.Code, CAST(cih.Time AS date)
ORDER BY cih.Time) AS NextClose
FROM CurrencyIntradayHistories cih
) cih
GROUP BY
cih.Code,
cih.Date
ORDER BY
cih.Date;
在整个数据集上使用 window 函数 MIN()、MAX() 和 FIRST_VALUE(),而不是在按代码和日期分组时得到的结果上:
SELECT DISTINCT
[Code],
FIRST_VALUE([Close]) OVER (PARTITION BY [Code], CONVERT(date, [Time]) ORDER BY [Time] ASC) AS [Open],
MAX([Close]) OVER (PARTITION BY [Code], CONVERT(date, [Time])) AS [High],
MIN([Close]) OVER (PARTITION BY [Code], CONVERT(date, [Time])) AS [Low],
FIRST_VALUE([Close]) OVER (PARTITION BY [Code], CONVERT(date, [Time]) ORDER BY [Time] DESC) AS [Close],
CONVERT(date, [Time]) [Time]
FROM [CurrencyIntradayHistories];
请参阅演示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.