3

我正在尝试将排名应用于我的数据集,逻辑如下:

对于每个 ID,Order by ID2 ASC 和 Order by IsMaster Desc 对第 1 行进行排名,并且仅在 ID4 值更改时才更改

我的数据集和所需的输出如下所示:

所需的输出]

测试数据

CREATE TABLE Test_Table 
(ID INT ,ID2 INT, IsMaster INT, ID4 VARCHAR(10))
GO

INSERT INTO Test_Table  (ID ,ID2 , IsMaster , ID4 )
VALUES 
 (1,    101,    1   ,'AAA')  -- 1  <-- Desired output for rank
,(1,    102,    0   ,'AAA')  -- 1
,(1,    103,    0   ,'AAB')  -- 2
,(1,    104,    0   ,'AAB')  -- 2
,(1,    105,    0   ,'CCC')  -- 3
,(2,    101,    1   ,'AAA')  -- 1
,(2,    102,    0   ,'AAA')  -- 1
,(2,    103,    0   ,'AAA')  -- 1
,(2,    104,    0   ,'AAB')  -- 2
,(2,    105,    0   ,'CCC')  -- 3

这是我到目前为止所尝试的:

SELECT *
    ,DENSE_RANK() OVER (PARTITION BY ID  ORDER BY ID2 ASC, IsMaster DESC ) rn
FROM Test_Table

请帮帮我谢谢。

4

4 回答 4

3

这是一个孤岛/差距问题。

  • 首先你LAG()用来查看在同一个分区上是否有不同的 ID4。
    • 很重要你也需要partition by IsMaster
  • 然后创建islandsID4 更改的时间。
  • 最后使用comulativeSUM()获得正确的排名。

Sql 演示

WITH id4_change as (
    SELECT  *, 
            LAG(ID4) OVER (PARTITION BY ID, IsMaster ORDER BY ID2) as prev
    FROM Test_Table
), islands as (
    SELECT *, 
           CASE WHEN ID4 = PREV 
                THEN 0 
                ELSE 1 
           END as island
    FROM id4_change
) 
SELECT *,
       SUM(island) OVER (PARTITION BY ID, IsMaster ORDER BY ID2) rank
FROM islands       
ORDER BY ID, ID2, IsMaster DESC
;

输出:你可以看到什么时候ID4 = PREV没有创建一个新的"Island"所以有相同的排名。

在此处输入图像描述

编辑:您可以简化前两个查询

WITH id4_change as (
    SELECT  *, 
            CASE WHEN ID4 = LAG(ID4) OVER (PARTITION BY ID, IsMaster ORDER BY ID2)
                 THEN 0
                 ELSE 1
            END as island
    FROM Test_Table
) 
SELECT *,
       SUM(island) OVER (PARTITION BY ID, IsMaster ORDER BY ID2) rank
FROM id4_change       
ORDER BY ID, ID2, IsMaster DESC
;
于 2017-03-15T15:17:06.060 回答
1

这应该为您提供当前输入集所需的输出:

SELECT *
    ,DENSE_RANK() OVER (PARTITION BY ID  ORDER BY ID4 ASC ) rn
FROM Test_Table

您的密集排名基于具有重复项的 ID4 列,而不是看起来唯一的 ID2 列。如果数据以不同的方式排序,这将不起作用,因此为了对此进行调整,您需要在最终语句中包含 ORDER BY 子句,如下所示:

CREATE TABLE Test_Table 
(ID INT ,ID2 INT, IsMaster INT, ID4 VARCHAR(10))
GO

INSERT INTO Test_Table  (ID ,ID2 , IsMaster , ID4 )
VALUES 
 (1,    102,    0   ,'AAA')  -- 1
,(1,    103,    0   ,'AAB')  -- 2
,(1,    104,    0   ,'AAB')  -- 2
,(1,    105,    0   ,'CCC')  -- 3
,(2,    102,    0   ,'AAA')  -- 1
,(2,    103,    0   ,'AAA')  -- 1
,(2,    104,    0   ,'AAB')  -- 2
,(2,    105,    0   ,'CCC')  -- 3
,(1,    101,    1   ,'AAA')  -- 1  <-- Reordered inputs
,(2,    101,    1   ,'AAA')  -- 1

SELECT *
    ,DENSE_RANK() OVER (PARTITION BY ID  ORDER BY ID4 ASC ) rn
FROM Test_Table
ORDER BY ID, rn, IsMaster DESC
于 2017-03-15T14:00:20.030 回答
1

另一种方法可能效率较低,但它会起作用。

WITH X AS
(
 SELECT *
       ,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID2) RowNum
 FROM dbo.Test_Table
)
, CTE_VehicleNumber
as
(
    SELECT  T.ID , T.ID2, t.IsMaster ,T.ID4 , t.RowNum  , 1 as [Rank]
    FROM X  as T
    WHERE T.IsMaster = 1 

    UNION ALL

    SELECT  T.ID, T.ID2, t.IsMaster ,T.ID4 , t.RowNum , CASE WHEN t.ID4 <> c.ID4 THEN 1+ C.[Rank]
                                                              ELSE 0+ C.[Rank]
                                                         END  as [Rank]
    FROM CTE_VehicleNumber as C
        inner join X  as T ON T.RowNum = C.RowNum + 1
                                              AND t.ID = c.ID
)
SELECT ID , ID2, IsMaster ,ID4  , [Rank] 
FROM CTE_VehicleNumber 
ORDER BY ID , ID2, IsMaster ,ID4  , [Rank]
OPTION (MAXRECURSION 0);
于 2017-03-21T18:04:24.620 回答
0

考虑到和中的其余数据,您确定您的订单ID2并影响了预期的结果吗?IsMasterIDID4

我只是尝试使用以下代码:

; WITH CTE AS (
    SELECT DISTINCT ID, ID4, DENSE_RANK() OVER (ORDER BY ID4) Rnk
    FROM #Test_Table
)
SELECT t.*, c.Rnk
FROM #Test_Table t
    INNER JOIN CTE c ON t.ID = c.ID AND t.ID4 = c.ID4;

...即使改变了的顺序,ID2IsMaster也不能让它“行为不端”——如果IsMaster = 1每组只有一个ID4's 而ID2.

于 2017-03-15T14:17:15.177 回答