获取第n个连续组的第一行/最后一行

Tim*_*ter 7 sql t-sql sql-server sql-server-2005

从第n组中选择单个记录/值的最简单方法是什么?该组由材料及其价格决定(价格可能会发生变化).我需要找到最后一个物料价格组的最后一个日期和最后一个日期.所以我想知道什么时候价格确实改变了.

我已经尝试过以下查询来获取当前(最后)价格的第一个日期,如果之前使用了该价格,则可以返回错误的日期:

DECLARE @material VARCHAR(20)
SET @material = '1271-4303'

SELECT TOP 1 Claim_Submitted_Date 
FROM   tabdata
WHERE Material = @material 
AND Price = (SELECT TOP 1 Price FROM tabdata t2 
             WHERE Material = @material
             ORDER BY Claim_Submitted_Date DESC)
ORDER BY Claim_Submitted_Date ASC
Run Code Online (Sandbox Code Playgroud)

这也只返回最后一次,我怎么得到以前的?那么上次/先前使用前一个价格的日期呢?

我已经简化了我的架构并使用sample-data 创建了这个sql-fiddle.这里按时间顺序排列.所以ID = 7的行是我需要的,因为它具有与最新日期的倒数第二个价格.

ID   CLAIM_SUBMITTED_DATE                   MATERIAL    PRICE
5   December, 04 2013 12:33:00+0000         1271-4303   20
4   December, 03 2013 12:33:00+0000         1271-4303   20   <-- current
3   November, 17 2013 10:13:00+0000         1271-4846   40
7   November, 08 2013 12:16:00+0000         1271-4303   18   <-- last(desired)
2   October, 17 2013 09:13:00+0000          1271-4303   18
1   September, 17 2013 08:13:00+0000        1271-4303   10
8   September, 16 2013 12:15:00+0000        1271-4303   17
6   June, 23 2013 14:22:00+0000             1271-4303   18
9   January, 11 2013 12:22:10+0000          1271-4303   20   <-- a problem since this is older than the desired but will be returned by my simply sub-query approach above
Run Code Online (Sandbox Code Playgroud)

甚至可以参数化这个值,所以nthLatestPriceGroup如果我想知道第3个最后的价格日期?请注意,查询位于标量值函数中.

编辑:非常感谢大家.但不幸的是,一个简单ROW_NUMBER似乎没有帮助,因为我试图在给定材料的当前价格之前获得最近价格的行.因此GROUP BY/ PARTITION BY material,price包含具有相同价格的行,这些行不属于最近的最近物料价格组.

考虑价格可以改变

Date             Price     Comment
5 months ago     20        original price, note that this is the same as the curent which causes my query to fail!
3 months ago     18        price has changed, i might need the first and last date
2 months ago     20        price has changed, i might need the first and last date
1 month ago      18        previous price, i need the oldest and newest dates 
NOW              20        current price, i need the first/oldest date from this group
Run Code Online (Sandbox Code Playgroud)

所以我想要最后一组20组最近一行的日期,最老的20组是不相关的.因此,我必须以某种方式按连续价格进行分组,因为价格在价格已经发生变化后可以重复.

所以实际上我只需Claim_Submitted_Date要从1 month ago ... previous price上面的列表中开始的价格组中最新的,这是直到前一个价格有效的日期.评论中列出的其他信息很好(nthLatestPriceGroup子问题).这是ID=7上面的示例数据中的行.顺便说一句,这个价格组中最老的一行是ID=2(10月17日),而不是ID=6(6月23日),即使后者年龄较大.之后有不同的价格(10).这就是为什么我不能使用简单的排名功能的原因.

Mac*_*ack 4

您将需要在子查询中使用窗口函数 ROWNUMBER,...

像这样的事情会让你到达那里:

ROW_NUMBER() OVER(PARTITION BY Price ORDER BY Claim_Submitted_Date DESC) AS Row 
Run Code Online (Sandbox Code Playgroud)

这是根据您的小提琴进行的更新:

DECLARE @material VARCHAR(20)
SET @material = '1271-4303'


SELECT * FROM
(
SELECT  *,
        ROW_NUMBER() OVER(PARTITION BY Material ORDER BY Claim_Submitted_Date ASC) AS rn  
FROM tabdata t2 
WHERE Material = @material
) res
WHERE rn=2
Run Code Online (Sandbox Code Playgroud)

如果 idData 是增量的(因此是按时间顺序排列的),你可以使用这个:

SELECT * FROM
(
SELECT  *,
        ROW_NUMBER() OVER(PARTITION BY Material ORDER BY idData DESC) AS rn  
FROM tabdata t2 
WHERE Material = @material
) res
Run Code Online (Sandbox Code Playgroud)

看看您的最新要求,我们可能都想太多了(如果我理解正确的话):

DECLARE @MATERIAL AS VARCHAR(9)
SET @MATERIAL = '1271-4303'

SELECT  TOP 1 *
FROM tabdata t2 
WHERE Material = @material
AND PRICE <> (  SELECT TOP 1 Price
                FROM tabdata 
                WHERE Material = @material 
                ORDER BY CLAIM_SUBMITTED_DATE desc)
ORDER BY CLAIM_SUBMITTED_DATE desc

--results
idData  Claim_Submitted_Date        Material    Price
7       2013-11-08 12:16:00.000     1271-4303   18
Run Code Online (Sandbox Code Playgroud)

这是一个基于此的小提琴。