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).这就是为什么我不能使用简单的排名功能的原因.
您将需要在子查询中使用窗口函数 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)
这是一个基于此的小提琴。