我需要在价格变化时列出frist记录。使用下面的例子。
发票表记录(按客户分组价格并按日期排序)
Index Customer Date Price
01 A May-01-2016 $12.00
02 A May-11-2016 $12.00
03 A May-21-2016 $13.00
04 A May-22-2016 $13.00
05 A May-23-2016 $13.00
06 A May-24-2016 $13.00
07 A Jun-01-2016 $14.00
08 A Jun-11-2016 $14.00
09 A Jun-21-2016 $14.00
10 A Jun-25-2016 $14.00
11 B May-02-2016 $12.50
12 B May-12-2016 $12.50
13 B May-22-2016 $13.50
14 B May-24-2016 $13.80
15 B May-26-2016 $13.80
16 B May-28-2016 $13.80
17 B Jun-02-2016 $14.60
18 B Jun-12-2016 $14.60
19 B Jun-22-2016 $14.60
20 B Jun-26-2016 $14.60
我需要在价格变化时获得第一条记录。结果将是:
01 A May-01-2016 $12.00
03 A May-21-2016 $13.00
07 A Jun-01-2016 $14.00
11 B May-02-2016 $12.50
13 B May-22-2016 $13.50
14 B May-24-2016 $13.80
17 B Jun-02-2016 $14.60
除了查询之外,我可以将结果限制为每个客户的最新2条记录吗?结果将是:
03 A May-21-2016 $13.00
07 A Jun-01-2016 $14.00
14 B May-24-2016 $13.80
17 B Jun-02-2016 $14.60
谢谢。
答案 0 :(得分:1)
第一部分:
SELECT id, customer, dte, price
FROM (SELECT id, customer, dte, price
,COALESCE(LAG(price) OVER(PARTITION BY customer ORDER BY id), price - 1) AS prev_price
FROM invoice) x
WHERE x.price <> x.prev_price
ORDER BY x.id
第二部分:
SELECT id, customer, dte, price
FROM (SELECT id, customer, dte, price
,ROW_NUMBER() OVER (PARTITION BY customer ORDER BY id DESC) AS row_num
FROM (SELECT id, customer, dte, price
,COALESCE(LAG(price) OVER (PARTITION BY customer ORDER BY id), price - 1) AS prev_price
FROM invoice) x
WHERE x.price <> x.prev_price) y
WHERE row_num <= 2
ORDER BY id
答案 1 :(得分:1)
;WITH CTE AS (
SELECT * ,
CAST(SUBSTRING([Date], 5,2) + '-'
+ LEFT([Date] , 3)
+ '-' + RIGHT([Date] ,4) AS DATE) AS DateDt
FROM Invoice)
,CTE2 AS
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY Price , Customer ORDER BY DateDt ASC) rn
FROM CTE
)
SELECT [Index] ,Customer, [Date] ,Price
FROM CTE2
where rn = 1
ORDER BY Customer , DateDt
╔═══════╦══════════╦═════════════╦═══════╗
║ Index ║ Customer ║ Date ║ Price ║
╠═══════╬══════════╬═════════════╬═══════╣
║ 01 ║ A ║ May-01-2016 ║ 12.00 ║
║ 03 ║ A ║ May-21-2016 ║ 13.00 ║
║ 07 ║ A ║ Jun-01-2016 ║ 14.00 ║
║ 11 ║ B ║ May-02-2016 ║ 12.50 ║
║ 13 ║ B ║ May-22-2016 ║ 13.50 ║
║ 14 ║ B ║ May-24-2016 ║ 13.80 ║
║ 17 ║ B ║ Jun-02-2016 ║ 14.60 ║
╚═══════╩══════════╩═════════════╩═══════╝
答案 2 :(得分:0)
假设日期列在某个有效的日期格式中(否则你应该将其转换),这是另一种方法:
;with cte as (
select
Invoice.[index], Invoice.Customer, Invoice.Date, Invoice.Price,
rn = row_number() over (partition by Invoice.customer order by date desc)
from Invoice
join (
select Customer, price, min(date) min_date
from Invoice
group by Customer, price
) t1 on Invoice.Customer = t1.Customer and Invoice.Date = t1.min_date
)
select [index], Customer, date, price
from cte where rn <= 2 order by [index]
此外, index 是一个保留关键字,因此对于列名称来说是一个糟糕的选择。
使用您的样本数据,输出将是:
index Customer date price
3 A 2016-05-21 $13.00
7 A 2016-06-01 $14.00
14 B 2016-05-24 $13.80
17 B 2016-06-02 $14.60
如果您正在使用SQL Server 2012+,则可以使用窗口化聚合函数并执行此查询,这可能更高效(或不):
select [index], Customer, date, price
from (
select *, rn = dense_rank() over (partition by customer order by min_date desc)
from (select *, min(date) over (partition by customer, price) min_date from Invoice) a
) b where rn <= 2 and Date = min_date order by [index]