在一列上排名 table 而在另一列上排序

Ranking table on one column whilst sorting on another

我有一个 SQL Server 2008 R2 table 的子集,如下所示:

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

我需要像这样对不同的价格周期进行排名:

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

以便它按 cust_idprod_idday 升序排序,但会在价格变化时增加排名。我试过像这样使用 DENSE_RANK()

SELECT 
    cust_id, prod_id, [day], price, 
    DENSE_RANK() OVER (ORDER BY cust_id, prod_id, price)
FROM
    @prices 

这 returns 类似于:

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

显然,从排序中排除这一天会得到这些结果,但每当我按 DENSE_RANK() 的部分将这一天包含在顺序中时 - 它只是将每个新的一天划分为一个新的 ID....

有人知道这应该如何运作吗?感谢任何建议,如果需要可以提供更多信息

LAGSUM

的第一个变体
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

没有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

具有递归 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)