sam*_*l90 5 sql-server sorting sql-server-2008-r2 dense-rank
我有一个SQL Server 2008 R2表的子集,如下所示:
cust_id | prod_id | day | price
--------+---------+-----+-------
137656 194528 42373 9.11
137656 194528 42374 9.11
137656 194528 42375 9.61
137656 194528 42376 9.61
137656 194528 42377 9.11
137656 194528 42378 9.11
Run Code Online (Sandbox Code Playgroud)
我需要对不同的价格周期进行排名,如下所示:
cust_id | prod_id | day | price | rank
--------+---------+-----+-------+------
137656 194528 42373 9.11 1
137656 194528 42374 9.11 1
137656 194528 42375 9.61 2
137656 194528 42376 9.61 2
137656 194528 42377 9.11 3
137656 194528 42378 9.11 3
Run Code Online (Sandbox Code Playgroud)
因此,当价格变化时,它会按顺序排序cust_id,prod_id然后day上升,但会增加排名.我试过这样用DENSE_RANK():
SELECT
cust_id, prod_id, [day], price,
DENSE_RANK() OVER (ORDER BY cust_id, prod_id, price)
FROM
@prices
Run Code Online (Sandbox Code Playgroud)
这返回类似于:
cust_id | prod_id | day | price | rank
--------+---------+-----+-------+------
137656 194528 42373 9.11 1
137656 194528 42374 9.11 1
137656 194528 42377 9.11 1
137656 194528 42378 9.11 1
137656 194528 42375 9.61 2
137656 194528 42376 9.61 2
Run Code Online (Sandbox Code Playgroud)
显然,从排序中排除这一天将给我这些结果,但每当我按顺序包含订单中的DENSE_RANK()那一天时 - 它只是将每个新的一天划分为一个新的ID ....
有没有人对如何运作有任何想法?感谢任何建议,如果需要可以提供更多信息
第一个变体LAG与SUM
SELECT
*,
1+SUM(IncCount)OVER(PARTITION BY cust_id ORDER BY [day]) [rank]
--1+SUM(IncCount)OVER(PARTITION BY cust_id ORDER BY [day] ROWS BETWEEN unbounded preceding AND current row) [rank]
FROM
(
SELECT
*,
IIF(LAG(price)OVER(PARTITION BY cust_id ORDER BY [day])<>price,1,0) IncCount
--CASE WHEN LAG(price)OVER(PARTITION BY cust_id ORDER BY [day])<>price THEN 1 ELSE 0 END IncCount
FROM Test
) q
Run Code Online (Sandbox Code Playgroud)
第二种变体没有LAG
WITH numCTE AS(
SELECT *,ROW_NUMBER()OVER(PARTITION BY cust_id ORDER BY [day]) RowNum
FROM Test
)
SELECT
t1.*,
1+SUM(CASE WHEN t2.price<>t1.price THEN 1 ELSE 0 END)OVER(PARTITION BY t1.cust_id ORDER BY t1.[day]) [rank]
--1+SUM(CASE WHEN t2.price<>t1.price THEN 1 ELSE 0 END)OVER(PARTITION BY t1.cust_id ORDER BY t1.[day] ROWS BETWEEN unbounded preceding AND current row) [rank]
FROM numCTE t1
LEFT JOIN numCTE t2 ON t2.RowNum+1=t1.RowNum AND t2.cust_id=t1.cust_id
Run Code Online (Sandbox Code Playgroud)
具有递归 CTE 的第三种变体
WITH numCTE AS(
SELECT *,ROW_NUMBER()OVER(PARTITION BY cust_id ORDER BY [day]) RowNum
FROM Test
),
rankCTE AS(
SELECT RowNum,cust_id,prod_id,[day],price,1 [rank]
FROM numCTE
WHERE RowNum=1
UNION ALL
SELECT
n.RowNum,n.cust_id,n.prod_id,n.[day],n.price,
r.[rank]+CASE WHEN n.price<>r.price THEN 1 ELSE 0 END [rank]
FROM numCTE n
JOIN rankCTE r ON n.RowNum=r.RowNum+1 AND n.cust_id=r.cust_id
)
SELECT *
FROM rankCTE
OPTION(MAXRECURSION 0)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
85 次 |
| 最近记录: |