Sql 关于在另一个表上记录间隔的GroupBy
我为我的问题准备了一把sql小提琴。这里有一个工作代码。我想问的是,是否存在我认为不存在的替代解决办法Sql 关于在另一个表上记录间隔的GroupBy,sql,sql-server,Sql,Sql Server,我为我的问题准备了一把sql小提琴。这里有一个工作代码。我想问的是,是否存在我认为不存在的替代解决办法 CREATE TABLE [Product] ([Timestamp] bigint NOT NULL PRIMARY KEY, [Value] float NOT NULL ) ; CREATE TABLE [PriceTable] ([Timestamp] bigint NOT NULL PRIMARY KEY, [Price] float
CREATE TABLE [Product]
([Timestamp] bigint NOT NULL PRIMARY KEY,
[Value] float NOT NULL
)
;
CREATE TABLE [PriceTable]
([Timestamp] bigint NOT NULL PRIMARY KEY,
[Price] float NOT NULL
)
;
INSERT INTO [Product]
([Timestamp], [Value])
VALUES
(1, 5),
(2, 3),
(4, 9),
(5, 2),
(7, 11),
(9, 3)
;
INSERT INTO [PriceTable]
([Timestamp], [Price])
VALUES
(1, 1),
(3, 4),
(7, 2.5),
(10, 3)
;
查询:
SELECT [Totals].*, [PriceTable].[Price]
FROM
(
SELECT [PriceTable].[Timestamp]
,SUM([Value]) AS [TotalValue]
FROM [Product],
[PriceTable]
WHERE [PriceTable].[Timestamp] <= [Product].[Timestamp]
AND NOT EXISTS (SELECT * FROM [dbo].[PriceTable] pt
WHERE pt.[Timestamp] <= [Product].[Timestamp]
AND pt.[Timestamp] > [PriceTable].[Timestamp])
GROUP BY [PriceTable].[Timestamp]
) AS [Totals]
INNER JOIN [dbo].[PriceTable]
ON [PriceTable].[Timestamp] = [Totals].[Timestamp]
ORDER BY [PriceTable].[Timestamp]
这里,我的第一个表[Product]包含不同时间戳的产品值。第二个表[价格表]包含不同时间间隔的价格。给定的价格在设置新价格之前有效。因此,时间戳为1的价格对时间戳为1和2的产品有效
我正试图得到与给定价格相关的产品总数。小提琴上的SQL产生了我所期望的结果
有没有更聪明的方法可以得到同样的结果
顺便说一句,我正在使用SQLServer2014。我想我有一个更容易阅读的查询。这对你有用吗
select pt.*,
(select sum(P.Value) from Product P where
P.TimeStamp between pt.TimeStamp and (
--get the next time stamp
select min(TimeStamp)-1 from PriceTable where TimeStamp > pt.TimeStamp
)) as TotalValue from PriceTable pt
--exclude entries with timestamps greater than those in Product table
where pt.TimeStamp < (select max(TimeStamp) from Product)
非常详细的问题顺便说一下
DECLARE @Product TABLE
(
[Timestamp] BIGINT NOT NULL
PRIMARY KEY ,
[Value] FLOAT NOT NULL
);
DECLARE @PriceTable TABLE
(
[Timestamp] BIGINT NOT NULL
PRIMARY KEY ,
[Price] FLOAT NOT NULL
);
INSERT INTO @Product
( [Timestamp], [Value] )
VALUES ( 1, 5 ),
( 2, 3 ),
( 4, 9 ),
( 5, 2 ),
( 7, 11 ),
( 9, 3 );
INSERT INTO @PriceTable
( [Timestamp], [Price] )
VALUES ( 1, 1 ),
( 3, 4 ),
( 7, 2.5 ),
( 10, 3 );
WITH cte
AS ( SELECT * ,
LEAD(pt.[Timestamp]) OVER ( ORDER BY pt.[Timestamp] ) AS [lTimestamp]
FROM @PriceTable pt
)
SELECT cte.[Timestamp] ,
( SELECT SUM(Value)
FROM @Product
WHERE [Timestamp] >= cte.[Timestamp]
AND [Timestamp] < cte.[lTimestamp]
) AS [TotalValue],
cte.[Price]
FROM cte
并将这些时间间隔内的所有值相加
输出:
Timestamp TotalValue Price
1 8 1
3 11 4
7 14 2.5
10 NULL 3
如果要过滤掉没有订单的行,只需添加WHERE子句即可
如果要关闭最后一个间隔,您还可以指示LEAD window函数的默认值,如:
LEAD(pt.[Timestamp], 1, 100)
我猜在制作中会是这样的:
LEAD(pt.[Timestamp], 1, GETDATE())
你可以用cte
;with cte as
(
select p1.[timestamp] as lowval,
case
when p2.[timestamp] is not null then p2.[timestamp] - 1
else 999999
end hival,
p1.price
from
(
select p1.[timestamp],p1.price,
row_number() over (order by p1.[timestamp]) rn
from pricetable p1 ) p1
left outer join
(select p1.[timestamp],p1.price,
row_number() over (order by p1.[timestamp]) rn
from pricetable p1) p2
on p2.rn = p1.rn + 1
)
select cte.lowval as 'timestamp',sum(p1.value) TotalValue,cte.price
from product p1
join cte on p1.[Timestamp] between cte.lowval and cte.hival
group by cte.lowval,cte.price
order by cte.lowval
它更容易理解,而且执行计划比您的查询便宜约10%请从fiddle发布所有表DDL,并在此处提供数据示例。SQLFiddle只是帮助我们帮助您的另一个工具。另外还有一个是为了感谢您的努力。很好,我将在实际数据上尝试这些解决方案。无论如何谢谢你,你需要排除最后一行10-空
LEAD(pt.[Timestamp], 1, GETDATE())
;with cte as
(
select p1.[timestamp] as lowval,
case
when p2.[timestamp] is not null then p2.[timestamp] - 1
else 999999
end hival,
p1.price
from
(
select p1.[timestamp],p1.price,
row_number() over (order by p1.[timestamp]) rn
from pricetable p1 ) p1
left outer join
(select p1.[timestamp],p1.price,
row_number() over (order by p1.[timestamp]) rn
from pricetable p1) p2
on p2.rn = p1.rn + 1
)
select cte.lowval as 'timestamp',sum(p1.value) TotalValue,cte.price
from product p1
join cte on p1.[Timestamp] between cte.lowval and cte.hival
group by cte.lowval,cte.price
order by cte.lowval