Dense_Rank 订购

Dense_Rank ordering

我读过这个问题的一些变体,但解决方案似乎不起作用。

我希望为每个 "OrderNo" 和 "GroupID" 动态创建一个 "Subgroup"。子组应按 "OrderLine" 排序,例如:(预期结果)

OrderNo OrderLine   GroupID Subgroup
------------------------------------
10463   1            798    1
10463   2            799    2
10463   3            797    3
10463   5            65     4
10463   6            65     4
10463   7            65     4
10481   4            917    1
10481   5            918    2
10481   6            131    3
10481   7            131    3
10481   8            131    3
10481   9            130    4

我在下面使用 Dense_Rank() 创建了正确的组,但排序(和排名)完全不正确。

SELECT 
    OrderNo, OrderLine, GroupID,
    DENSE_RANK() OVER (PARTITION BY OrderNo ORDER BY GroupID) AS Subgroup
FROM 
    #temptable
ORDER BY
    OrderNo, OrderLine;

输出:

OrderNo OrderLine   GroupID Subgroup
------------------------------------
10463   1            798    3
10463   2            799    4
10463   3            797    2
10463   5            65     1
10463   6            65     1
10463   7            65     1
10481   4            917    3
10481   5            918    4
10481   6            131    2
10481   7            131    2
10481   8            131    2
10481   9            130    1

查询:

-- Temp tables
CREATE TABLE #temptable
(  
    OrderNo varchar(5),  
    OrderLine int, 
    GroupID int
); 

INSERT INTO #temptable (OrderNo, OrderLine, GroupID)
VALUES ('10463', '1', '798'), ('10463', '2', '799'),
       ('10463', '3', '797'), ('10463', '5', '65'),
       ('10463', '6', '65'), ('10463', '7', '65'),
       ('10481', '4', '917'), ('10481', '5', '918'),
       ('10481', '6', '131'), ('10481', '7', '131'),
       ('10481', '8', '131'), ('10481', '9', '130');

您想按 OrderLineDENSE_RANK 分区进行排序,但在多个记录具有相同 GroupID 的情况下,您希望排名相同。一种选择是使用子查询来识别为具有相同 GroupID 的一组记录分配单个值 OrderLine(比如最小值)。然后可以将此 table 连接回您的 #temptable,并且可以根据需要将有效的 OrderLine 用于 DENSE_RANK

SELECT t1.OrderNo,
       t1.OrderLine,
       t1.GroupID,
       DENSE_RANK() OVER (PARTITION BY t1.OrderNo ORDER BY t2.OrderLine) AS Subgroup
FROM #temptable t1
INNER JOIN
(
    SELECT OrderNo,
           MIN(OrderLine) AS OrderLine,
           GroupID
    FROM #temptable
    GROUP BY OrderNo,
             GroupID
) t2
    ON t1.OrderNo = t2.OrderNo AND
       t1.GroupID = t2.GroupID