在上一个问题中如何合并数据集而不包括冗余行?我询问了在导入过程中过滤冗余历史数据的问题,但@DavidSpillett 正确回答说我无法做我想做的事情。
我现在不想在导入过程中过滤表,而是想在表上创建一个视图,该视图仅返回价格发生变化的记录。
这是为解决这个问题而改写的原始场景:
我们有一个物品的历史价格表。该表包含多个日期记录相同价格的行。我想在此数据上创建一个视图,该视图仅显示价格随时间的变化,因此如果价格从 A 更改为 BI 想要查看它,但如果它从 B“更改”为 B 那么我不想看到它.
例子:如果昨天的价格是$1,今天的价格是$1,并且没有其他价格变化,那么今天的价格可以从昨天的价格推断出来,所以我只需要昨天的记录。
示例(http://sqlfiddle.com/#!3/c95ff/1):
Table data:
Effective Product Kind Price
2013-04-23T00:23:00 1234 1 1.00
2013-04-24T00:24:00 1234 1 1.00 -- redundant, implied by record 1
2013-04-25T00:25:00 1234 1 1.50
2013-04-26T00:26:00 1234 1 2.00
2013-04-27T00:27:00 1234 1 2.00 -- redundant, implied by record 4
2013-04-28T00:28:00 1234 1 1.00 -- not redundant, price changed back to 1.00
Expected view data:
Effective Product Kind Price
2013-04-23T00:23:00 1234 1 1.00
2013-04-25T00:25:00 1234 1 1.50
2013-04-26T00:26:00 1234 1 2.00
2013-04-28T00:28:00 1234 1 1.00
Run Code Online (Sandbox Code Playgroud)
我最初的尝试使用 ROW_NUMBER:
SELECT
Effective,
Product,
Kind,
Price
FROM
(
SELECT
History.*,
ROW_NUMBER() OVER
(
PARTITION BY
Product,
Kind,
Price
ORDER BY
Effective ASC
) AS RowNumber
FROM History
) H
WHERE RowNumber = 1
ORDER BY Effective
Run Code Online (Sandbox Code Playgroud)
哪个返回:
Effective Product Kind Price
2013-04-23T00:23:00 1234 1 1.00
-- not 2013-04-24, good
2013-04-25T00:25:00 1234 1 1.50
2013-04-26T00:26:00 1234 1 2.00
-- not 2013-04-27, good
-- not 2013-04-28, bad
Run Code Online (Sandbox Code Playgroud)
我尝试搜索类似的问题/答案,但很难弄清楚如何表达搜索,一个例子值得很多词。
任何建议表示赞赏。谢谢
SELECT H.*
FROM History AS H
OUTER APPLY
(
SELECT TOP (1)
H2.Price
FROM History AS H2
WHERE
H2.Product = H.Product
AND H2.Kind = H.Kind
AND H2.Effective < H.Effective
ORDER BY
H2.Effective DESC
) AS X
WHERE
NOT EXISTS (SELECT X.Price INTERSECT SELECT H.Price);
Run Code Online (Sandbox Code Playgroud)
对于问题中给出的少量行,这是一个很好的执行计划。对于较大的表,此查询的理想索引是:
CREATE UNIQUE INDEX [dbo.History Product, Kind, Effective]
ON dbo.History (Product, Kind, Effective DESC)
INCLUDE (Price);
Run Code Online (Sandbox Code Playgroud)
该索引本质上是按更有用的顺序排列的聚集索引键。根据表用于其他查询的方式,最好替换聚集索引而不是创建此新索引。
不要使用批量估计成本百分比来比较不同的查询。一般来说,这不是一个有效的比较。成本始终是优化器估计,而不是打算以这种方式使用。一定要检查实际的性能指标(运行时间、I/O、CPU 使用率、内存使用率),但不要相信百分比。
这种查询还是基于查询的ROW_NUMBER
效率更高取决于数据的分布和其他因素。每个都有其优点和缺点。当每个(产品、种类)组合有很多行时,此查询具有优势。
SELECT *
FROM (SELECT TOP 1 *
FROM History
ORDER BY Effective ASC) AS f
UNION ALL
SELECT *
FROM History AS a
WHERE a.Price <> (SELECT TOP 1 Price
FROM History AS b
WHERE b.Effective < a.Effective
ORDER BY Effective DESC)
ORDER BY Effective ASC ;
Run Code Online (Sandbox Code Playgroud)
在SQL-Fiddle测试