选择价格没有变化的行
Posted
技术标签:
【中文标题】选择价格没有变化的行【英文标题】:Select rows where price didn't change 【发布时间】:2011-01-19 17:33:04 【问题描述】:假设您有一个类似的表(我使用的是 SQL Server 2008,没有审核日志 - 表很大):
SecID | Date | Price
1 1/1/11 10
1 1/2/11 10
1 1/3/11 5
1 1/4/11 10
1 1/5/11 10
假设这个表是巨大的(不同的 secID 和日期有数百万行)- 我想在价格变化时返回记录(寻找比使用游标和迭代更好的东西):
我想知道如何获得:
SecID | StartDate | EndDate | Price
1 1/1/11 1/2/11 10
1 1/3/11 1/3/11 5
1 1/4/11 1/5/11 10
即另一种看待它的方式是,我正在寻找价格保持不变的日期范围。
【问题讨论】:
您是否将此信息存储在另一个表中(即审核日志)? 不清楚你想要什么——它是一组记录指定价格保持不变的日期范围吗? @Larry,是的,正是我要找的东西 如果价格发生变化,然后又改回您日期范围内的原始值怎么办?你想包含它吗? @Matthew - 是的。 (参见示例结果,其中 10 显示了两次) 【参考方案1】:这是一个“孤岛”问题。
declare @Yourtable table
(SecID int, Date Date, Price int)
INSERT INTO @Yourtable
SELECT 1,GETDATE()-5,10 union all
SELECT 1,GETDATE()-4,10 union all
SELECT 1,GETDATE()-3,5 union all
SELECT 1,GETDATE()-2,10 union all
SELECT 1,GETDATE()-1, 10
;WITH cte AS
(
SELECT SecID,Date,Price,
ROW_NUMBER() OVER (PARTITION BY SecID ORDER BY Date) -
ROW_NUMBER() OVER (PARTITION BY Price, SecID ORDER BY Date) AS Grp
FROM @Yourtable
)
SELECT SecID,Price, MIN(Date) StartDate, MAX(Date) EndDate
FROM cte
GROUP BY SecID, Grp, Price
ORDER BY SecID, MIN(Date)
【讨论】:
其实这个答案比我的好:) 顺便说一句,什么是“孤岛”问题? @Denis - 在您的问题中查找连续的数据“岛”。我的答案中的解决方案基于我最初在 Itzik Ben Gan 的一本书中读到的方法。【参考方案2】:如果值不变,则标准偏差为零
select secId
from ...
group by secId
having count(*) = 1
OR stdev(price) = 0
【讨论】:
@Matthew,除了必须读取每一行之外,我无法想象它会增加多少,因为磁盘读取会淹没任何正在进行的内存操作。【参考方案3】:我认为这应该可行
SELECT SecID, Min(Date) AS StartDate, Max(Date) AS EndDate, Price FROM BigTable GROUP BY SecID, EndDate Having Min(Date) != MAx(Date) And Date != NULL
【讨论】:
这不起作用,因为在我的示例的第 2 行 Min(Date) = Max(Date) 并且最后一行将被删除(因为 price = 10 已经在第一行中找到)。不过很好的尝试-考虑了一段时间。 (顺便说一句,日期被标记为“NOT NULL”) 您还应该按价格分组,而不是按结束日期分组。无论如何,如果你替换它,并取出HAVING
,它应该可以正常工作
这也行不通,因为如果您按 SecID、Price 分组,那么您的结果集中将有 (1, 10) 和 (1, 5) 所以 2 行。你应该有 3: (1, 10), (1, 5) 和 (1,10)。
是的,抱歉,已经有一段时间了 :)以上是关于选择价格没有变化的行的主要内容,如果未能解决你的问题,请参考以下文章