如何分区以分散价值?

时间:2019-05-28 11:16:33

标签: sql-server row-number data-partitioning

我有一个包含数据的表:

客户

  • 序列
  • ID
  • 其他许多列(不重要)

样本数据:

Sequence ID
-----------
214906 2613
214906 2614
214906 2615
214907 2613
214907 2614
214907 2615
214908 2613
214908 2614
214908 2615
214000 2613
213004 4444
111111 5555
111111 5556
111112 5556 
111112 5555

如何在下面获得所需的结果?

214906 2613
214907 2614
214908 2615
214000 2613
213004 4444
111111 5555
111112 5556

我用ROW_NUMBER() OVER(PARTITION BY Sequence)尝试了各种方法,但没有帮助,因为我需要将第一组的第一行,第二组的第二行等。换句话说,我需要以某种方式在ID上分布这些序列。我也无法按ID进行分区,因为它们可能在表中出现多次

1 个答案:

答案 0 :(得分:2)

我希望我能正确理解你。我将每个序列的ID数量用作组因子(使用SUM()OVER子句,不使用ORDER BY),然后进行适当的排名和行编号:

输入:

CREATE TABLE #Data (
    Sequence int,
    ID int
)
INSERT INTO #Data 
    (Sequence, ID)
VALUES
    (214906, 2613),
    (214906, 2614),
    (214906, 2615),
    (214907, 2613),
    (214907, 2614),
    (214907, 2615),
    (214908, 2613),
    (214908, 2614),
    (214908, 2615),
    (214000, 2613),
    (213004, 4444),
    (111111, 5555),
    (111111, 5556),
    (111112, 5556), 
    (111112, 5555)

T-SQL:

;WITH SequenceCTE AS (
    SELECT 
        *,
        COUNT(*) OVER (PARTITION BY Sequence) AS SequenceCnt
    FROM #Data
), RankCTE AS (
    SELECT 
        *,
        DENSE_RANK() OVER (PARTITION BY SequenceCnt, Sequence ORDER BY SequenceCnt, ID) AS RankNo,
        ROW_NUMBER() OVER (PARTITION BY SequenceCnt, ID ORDER BY Sequence, ID) AS RowNo
    FROM SequenceCTE 
)
SELECT Sequence, ID
FROM RankCTE
WHERE RankNo = RowNo

输出:

----------------
Sequence    ID
----------------
214000      2613
213004      4444
111111      5555
111112      5556
214906      2613
214907      2614
214908      2615

更新(特殊情况,序列中有一个ID)

;WITH SequenceCTE AS (
    SELECT 
        *,
        COUNT(*) OVER (PARTITION BY Sequence) AS SequenceCnt
    FROM #Data
), RankCTE AS (
    SELECT 
        *,
        CASE 
            WHEN SequenceCnt = 1 THEN 1
            ELSE DENSE_RANK() OVER (PARTITION BY SequenceCnt, Sequence ORDER BY SequenceCnt, ID) 
        END AS RankNo,
        CASE 
            WHEN SequenceCnt = 1 THEN 1
            ELSE ROW_NUMBER() OVER (PARTITION BY SequenceCnt, ID ORDER BY Sequence, ID) 
        END AS RowNo
    FROM SequenceCTE 
)
SELECT Sequence, ID
FROM RankCTE
WHERE RankNo = RowNo