查询 return 连续 X 天的最低值 SUM
Query to return the lowest SUM of values over X consecutive days
我什至不知道怎么说这个!...
我有一个包含两列的 table,价格(双精度)和开始日期(日期)。我需要能够查询 table 和 return X 行数,在这个例子中假设为 3 - 我需要拉回具有连续日期的 3 行,例如2019 年 5 月 7 日、8 日、9 日,具有日期范围内最低的价格总和值。
我在想一个接受 startDateRange、endDateRange、持续时间的函数。
它将 return startDateRange 和 endDateRange 之间的行数(持续时间)和这三行加起来将是该日期范围内任意数量行的最便宜(最低)总和对于连续的日期。
例如,如果我想要从 2019 年 5 月 1 日到 2019 年 5 月 14 日之间最便宜的 3 个日期,突出显示的 3 行将是 returned;
我认为 LEAD() 和 LAG() 可能是一个起点,但我不是一个真正的 SQL 人,所以不确定是否有更好的解决方法。
我目前已经在我的业务层上开发了一些 c# 来执行此操作,但是在大型数据集上它有点迟钝 - 直接从我的数据层获取记录列表会很好。
如有任何想法,我们将不胜感激!
提前致谢。
这是您的解决方案,当您开始声明日期时,逻辑就开始了。祝一切顺利。
--table example
declare @laVieja table (price float,fecha date )
insert into @laVieja values (632,'20150101')
insert into @laVieja values (649,'20150102')
insert into @laVieja values (632,'20150103')
insert into @laVieja values (607,'20150104')
insert into @laVieja values (598,'20150105')
insert into @laVieja values (624,'20150106')
insert into @laVieja values (641,'20150107')
insert into @laVieja values (598,'20150108')
insert into @laVieja values (556,'20150109')
insert into @laVieja values (480,'20150110')
insert into @laVieja values (510,'20150111')
insert into @laVieja values (541,'20150112')
insert into @laVieja values (634,'20150113')
insert into @laVieja values (634,'20150114')
-- end of setting up table example
--declaring dates
declare @fechaIni date, @fechaEnds date
set @fechaIni = '20150101'
set @fechaEnds = '20150114'
--assigning order based on price
select * , ROW_NUMBER() over (order by price) as unOrden
into #laVieja
from @laVieja
where fecha between @fechaIni and @fechaEnds
-- declaring variables for cycle
declare @iteracion float = 1 ,@iteracionMaxima float, @fechaPrimera date, @fechaSegunda date, @fechaTercera date
select @iteracionMaxima = max(unOrden) from #laVieja
--starting cycle
while(@iteracion <= @iteracionMaxima)
begin
--assigning dates to variables
select @fechaPrimera = fecha from #laVieja where unOrden = @iteracion
select @fechaSegunda = fecha from #laVieja where unOrden = @iteracion + 1
select @fechaTercera = fecha from #laVieja where unOrden = @iteracion + 2
--comparing variables
if(@fechaTercera = DATEADD(day,1,@fechaSegunda) and @fechaSegunda = DATEADD(day,1,@fechaPrimera))
begin
select * from #laVieja
where unOrden in (@iteracion,@iteracion+1,@iteracion+2)
set @iteracion = @iteracionMaxima
end
set @iteracion +=1
end
您可以使用 window 函数计算 3 天的平均值。然后使用 top 1
来选择具有最低平均值的 3 行的集合:
select top 1 StartDt
, AvgPrice
from (
select StartDt
, avg(Price) over (order by StartDt rows between 2 preceding
and current row) AvgPrice
, count(*) over (order by StartDt rows between 2 preceding
and current row) RowCnt
from prices
) sets_of_3_days
where RowCnt = 3 -- ignore first two rows
order by
AvgPrice desc
您可以使用带有 OVER (... ROWS BETWEEN)
子句的 window 函数来计算特定行数的 sum/average。然后,您可以使用 ROW_NUMBER
查找其他两行。
WITH cte1 AS (
SELECT *
, SUM(Price) OVER (ORDER BY Date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS wsum
, ROW_NUMBER() OVER (ORDER BY Date) AS rn
FROM #t
), cte2 AS (
SELECT TOP 1 rn
FROM cte1
WHERE rn > 2
ORDER BY wsum, Date
)
SELECT *
FROM cte1
WHERE rn BEtWEEN (SELECT rn FROM cte2) - 2 AND (SELECT rn FROM cte2)
在上面的查询中,将 2 替换为 window - 1.
的大小
我什至不知道怎么说这个!...
我有一个包含两列的 table,价格(双精度)和开始日期(日期)。我需要能够查询 table 和 return X 行数,在这个例子中假设为 3 - 我需要拉回具有连续日期的 3 行,例如2019 年 5 月 7 日、8 日、9 日,具有日期范围内最低的价格总和值。
我在想一个接受 startDateRange、endDateRange、持续时间的函数。
它将 return startDateRange 和 endDateRange 之间的行数(持续时间)和这三行加起来将是该日期范围内任意数量行的最便宜(最低)总和对于连续的日期。
例如,如果我想要从 2019 年 5 月 1 日到 2019 年 5 月 14 日之间最便宜的 3 个日期,突出显示的 3 行将是 returned;
我认为 LEAD() 和 LAG() 可能是一个起点,但我不是一个真正的 SQL 人,所以不确定是否有更好的解决方法。
我目前已经在我的业务层上开发了一些 c# 来执行此操作,但是在大型数据集上它有点迟钝 - 直接从我的数据层获取记录列表会很好。
如有任何想法,我们将不胜感激!
提前致谢。
这是您的解决方案,当您开始声明日期时,逻辑就开始了。祝一切顺利。
--table example
declare @laVieja table (price float,fecha date )
insert into @laVieja values (632,'20150101')
insert into @laVieja values (649,'20150102')
insert into @laVieja values (632,'20150103')
insert into @laVieja values (607,'20150104')
insert into @laVieja values (598,'20150105')
insert into @laVieja values (624,'20150106')
insert into @laVieja values (641,'20150107')
insert into @laVieja values (598,'20150108')
insert into @laVieja values (556,'20150109')
insert into @laVieja values (480,'20150110')
insert into @laVieja values (510,'20150111')
insert into @laVieja values (541,'20150112')
insert into @laVieja values (634,'20150113')
insert into @laVieja values (634,'20150114')
-- end of setting up table example
--declaring dates
declare @fechaIni date, @fechaEnds date
set @fechaIni = '20150101'
set @fechaEnds = '20150114'
--assigning order based on price
select * , ROW_NUMBER() over (order by price) as unOrden
into #laVieja
from @laVieja
where fecha between @fechaIni and @fechaEnds
-- declaring variables for cycle
declare @iteracion float = 1 ,@iteracionMaxima float, @fechaPrimera date, @fechaSegunda date, @fechaTercera date
select @iteracionMaxima = max(unOrden) from #laVieja
--starting cycle
while(@iteracion <= @iteracionMaxima)
begin
--assigning dates to variables
select @fechaPrimera = fecha from #laVieja where unOrden = @iteracion
select @fechaSegunda = fecha from #laVieja where unOrden = @iteracion + 1
select @fechaTercera = fecha from #laVieja where unOrden = @iteracion + 2
--comparing variables
if(@fechaTercera = DATEADD(day,1,@fechaSegunda) and @fechaSegunda = DATEADD(day,1,@fechaPrimera))
begin
select * from #laVieja
where unOrden in (@iteracion,@iteracion+1,@iteracion+2)
set @iteracion = @iteracionMaxima
end
set @iteracion +=1
end
您可以使用 window 函数计算 3 天的平均值。然后使用 top 1
来选择具有最低平均值的 3 行的集合:
select top 1 StartDt
, AvgPrice
from (
select StartDt
, avg(Price) over (order by StartDt rows between 2 preceding
and current row) AvgPrice
, count(*) over (order by StartDt rows between 2 preceding
and current row) RowCnt
from prices
) sets_of_3_days
where RowCnt = 3 -- ignore first two rows
order by
AvgPrice desc
您可以使用带有 OVER (... ROWS BETWEEN)
子句的 window 函数来计算特定行数的 sum/average。然后,您可以使用 ROW_NUMBER
查找其他两行。
WITH cte1 AS (
SELECT *
, SUM(Price) OVER (ORDER BY Date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS wsum
, ROW_NUMBER() OVER (ORDER BY Date) AS rn
FROM #t
), cte2 AS (
SELECT TOP 1 rn
FROM cte1
WHERE rn > 2
ORDER BY wsum, Date
)
SELECT *
FROM cte1
WHERE rn BEtWEEN (SELECT rn FROM cte2) - 2 AND (SELECT rn FROM cte2)
在上面的查询中,将 2 替换为 window - 1.
的大小