我在SQL Azure数据库中有一段时间的汇率表。
如:
1. USD-AUD, 2015-1-1 00:01, 0.70
2. USD-AUD, 2015-1-1 00:02, 0.73
3. USD-AUD, 2015-1-1 00:03, 0.69
4. USD-AUD, 2015-1-1 00:04, 0.78
5. USD-AUD, 2015-1-1 00:05, 0.75
6. USD-AUD, 2015-1-1 00:06, 0.80
(Pair, DateTime, ExchangeRate)
我想以5分钟的间隔进行分组,并显示最小速率,最大速率以及第一个(第1行)和最后一个(第5行)。因此开放将是0.70,高= 0.78,低= 0.69并且接近0.75
我已经在这里关注了如何分组哪些有用的线索,但我无法弄清楚如何获得"打开"和"关闭"
Select min(price) as low, max(price) as high
from exchangetable
(GROUP BY DATEPART(YEAR, [Time]),
DATEPART(MONTH, [Time]),
DATEPART(DAY, [Time]),
DATEPART(HOUR, [Time])
GROUP BY DATEPART(mi, [Time]) % 5
使用FIRST_VALUE
http://www.mssqltips.com/sqlservertip/2640/sql-server-2012-functions--firstvalue-and-lastvalue/我得到了#34;此版本的SQL错误不支持"
解决方案是加入自身还是游标?
答案 0 :(得分:1)
不需要游标。请尝试以下方法。请注意,我必须更改不一致的列名称。您还需要GROUP BY中的整数除法而不是模数运算符(%)。 “打开”和“关闭”列由子选择生成。
SELECT
DATEPART(YEAR, e1.[datetime]) AS Year,
DATEPART(MONTH, e1.[datetime]) AS Month,
DATEPART(DAY, e1.[datetime]) AS Day,
DATEPART(HOUR, e1.[datetime]) AS Hour,
DATEPART(mi, e1.[datetime])/5 AS TimeBracket,
(
SELECT TOP 1
e2.ExchangeRate
FROM
exchangetable e2
WHERE
DATEPART(YEAR, e1.[datetime]) = DATEPART(YEAR, e2.[datetime]) AND
DATEPART(MONTH, e1.[datetime]) = DATEPART(MONTH, e2.[datetime]) AND
DATEPART(DAY, e1.[datetime]) = DATEPART(DAY, e2.[datetime]) AND
DATEPART(HOUR, e1.[datetime]) = DATEPART(HOUR, e2.[datetime]) AND
DATEPART(MI, e1.[datetime])/5 = DATEPART(MI, e2.[datetime])/5
ORDER BY
[datetime]
) AS [Open],
(
SELECT TOP 1
e2.ExchangeRate
FROM
exchangetable e2
WHERE
DATEPART(YEAR, e1.[datetime]) = DATEPART(YEAR, e2.[datetime]) AND
DATEPART(MONTH, e1.[datetime]) = DATEPART(MONTH, e2.[datetime]) AND
DATEPART(DAY, e1.[datetime]) = DATEPART(DAY, e2.[datetime]) AND
DATEPART(HOUR, e1.[datetime]) = DATEPART(HOUR, e2.[datetime]) AND
DATEPART(MI, e1.[datetime])/5 = DATEPART(MI, DATEADD(MI, -1, e2.[datetime]))/5
ORDER BY
[datetime] DESC
) AS [Close],
MIN(ExchangeRate) AS low,
MAX(ExchangeRate) AS high
FROM
exchangetable e1
GROUP BY
DATEPART(YEAR, [datetime]),
DATEPART(MONTH, [datetime]),
DATEPART(DAY, [datetime]),
DATEPART(HOUR, [datetime]),
DATEPART(mi, [datetime])/5
哦和BTW我需要添加一个小时的日期部分,否则你会发现" TimeBrackets"从一天的不同部分聚集在一起。您的数据使用此查询生成以下结果:
Year Month Day Hour TimeBracket Open Close low high
2015 1 1 0 0 0.70 0.75 0.69 0.78
2015 1 1 0 1 0.75 0.80 0.75 0.80
答案 1 :(得分:0)
您可以将DENSE_RANK()
和ROW_NUMBER()
与PARTITION BY
一起使用,以获得您想要的内容。这样的事情。
代码说明:
DENSE_RANK()
根据当前日期,小时和分钟/ 5分配不同的Grp。
1st ROW_NUMBER
根据增加的时间从1开始在grp内分配唯一的数字。如果此数字为1,则该行是grp
第2个ROW_NUMBER
根据减少的时间从1开始在grp内分配唯一的数字。如果此数字为1,则该行是grp
<强>查询强>
;WITH exchangetable(Pair, [Time], Price) AS (
SELECT 'USD-AUD', '2015-1-1 00:01', 0.70
UNION ALL SELECT'USD-AUD', '2015-1-1 00:02', 0.73
UNION ALL SELECT'USD-AUD', '2015-1-1 00:03', 0.69
UNION ALL SELECT'USD-AUD', '2015-1-1 00:04', 0.78
UNION ALL SELECT'USD-AUD', '2015-1-1 00:05', 0.75
UNION ALL SELECT'USD-AUD', '2015-1-1 00:06', 0.80
), Grp as
(
Select
DENSE_RANK()OVER(ORDER BY CONVERT(DATE,[Time]),DATEPART(HOUR, [Time]),(DATEPART(mi, [Time]) / 5)) grp,
ROW_NUMBER()OVER(PARTITION BY CONVERT(DATE,[Time]),DATEPART(HOUR, [Time]),(DATEPART(mi, [Time]) / 5) ORDER BY [Time]) f_row,
ROW_NUMBER()OVER(PARTITION BY CONVERT(DATE,[Time]),DATEPART(HOUR, [Time]),(DATEPART(mi, [Time]) / 5) ORDER BY [Time] DESC) l_row,*
from exchangetable
)
SELECT G1.*,G_First.*,G_Last.*
FROM
(
SELECT grp,MAX(Price) max_price,MIN(Price) min_price
FROM Grp
GROUP BY grp
) G1
INNER JOIN Grp G_Last ON G_Last.grp = G1.grp AND G_Last.l_row = 1
INNER JOIN Grp G_First ON G_First.grp = G1.grp AND G_First.f_row = 1
答案 2 :(得分:0)
避免连接的另一种方法是使用
DATEADD(MINUTE, DATEDIFF(MINUTE, 0, [exchangetable].[Time]) / 5 * 5, 0)
作为我们的窗口期,然后在分析函数上使用SELECT DISTINCT
而不是GROUP BY
,因为我们通过[Time]
对项目进行排序,因此我们不想将其作为分组的一部分。
;WITH [exchangetable] ([Pair], [Time], [Price]) AS (
SELECT
'USD-AUD',
'2015-1-1 00:01',
0.70
UNION ALL
SELECT
'USD-AUD',
'2015-1-1 00:02',
0.73
UNION ALL
SELECT
'USD-AUD',
'2015-1-1 00:03',
0.69
UNION ALL
SELECT
'USD-AUD',
'2015-1-1 00:04',
0.78
UNION ALL
SELECT
'USD-AUD',
'2015-1-1 00:05',
0.75
UNION ALL
SELECT
'USD-AUD',
'2015-1-1 00:06',
0.80
),
[periods] AS (
SELECT
[PeriodNo] = DATEADD(MINUTE, DATEDIFF(MINUTE, 0, [exchangetable].[Time]) / 5 * 5, 0),
[exchangetable].[Pair],
[exchangetable].[Time],
[exchangetable].[Price]
FROM [exchangetable]
)
SELECT DISTINCT
[periods].[Pair],
[periods].[PeriodNo],
[StartTime] = FIRST_VALUE([periods].[Time]) OVER (PARTITION BY
[periods].[Pair],
[periods].[PeriodNo]
ORDER BY [periods].[Time]
),
[EndTime] = LAST_VALUE([periods].[Time]) OVER (PARTITION BY
[periods].[Pair],
[periods].[PeriodNo]
ORDER BY [periods].[Time]
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
),
[StartVal] = FIRST_VALUE([periods].[Price]) OVER (PARTITION BY
[periods].[Pair],
[periods].[PeriodNo]
ORDER BY [periods].[Time]
),
[EndVal] = LAST_VALUE([periods].[Price]) OVER (PARTITION BY
[periods].[Pair],
[periods].[PeriodNo]
ORDER BY [periods].[Time]
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
)
FROM [periods];