生成组中每组2的序列号

时间:2017-08-01 23:20:08

标签: sql sql-server

我有一个要求,我们需要在2的集合中为每个组生成序列号。

例如,在下面的屏幕截图中,我们让Workcenter对材质重复多次,我们需要在2的集合中生成序列号。

  • 因此,如果工作中心在操作1& 2(MONS003)然后 seq编号应为' 1'。
  • 如果工作中心在操作中相同 3& 4(MONS003)然后seq编号应为' 2'。

我们需要标记每组2的序列号。

在这个例子中作为Seq 1& 2(MONS003)已成为一组,即使工作中心对于操作2& 3(MONSO003)它需要移动到3& 3的下一组。 4(MONS003)。

因此,每组2需要标记新的序列号,如果它们在一个序列中。

是否可以生成类似于屏幕截图的“输出”列中的内容。 Screenshot

MATERIAL|NEW_OPR_SEQ|WORKCENTER|OUTPUT_FLAG
070147|1|MONSO003  |1
070147|2|MONSO003  |1
070147|3|MONSO003  |2
070147|4|MONSO003  |2
070147|5|MONSO003  |0
070147|6|MONGR025  |0
070147|7|VERSA008  |0
070147|8|LAGER     |0
912001|1|MONGR025  |0
912001|2|VERSA008  |1
912001|2|VERSA008  |1

1 个答案:

答案 0 :(得分:1)

使用DENSE_RANK Window Function的基本解决方案:

CREATE TABLE #Data( ID INT IDENTITY, MATERIAL VARCHAR( 10 ), NEW_OPR_SEQ INT, WORKCENTER VARCHAR( 20 ))
INSERT INTO #Data 
VALUES
( '070147', 1, 'MONSO003' ), ( '070147', 2, 'MONSO003' ), ( '070147', 3, 'MONSO003' ), ( '070147', 4, 'MONSO003' ),
( '070147', 5, 'MONSO003' ), ( '070147', 6, 'MONGR025' ), ( '070147', 7, 'VERSA008' ), ( '070147', 8, 'LAGER' ),
( '912001', 1, 'MONGR025' ), ( '912001', 2, 'VERSA008' ), ( '912001', 3, 'VERSA008' )

SELECT *,
        DENSE_RANK() OVER( PARTITION BY MATERIAL, WORKCENTER, NEW_OPR_SEQ % 2 ORDER BY NEW_OPR_SEQ ) AS GroupNumber
    FROM #Data

输出:

ID          MATERIAL   NEW_OPR_SEQ WORKCENTER           GroupNumber
----------- ---------- ----------- -------------------- --------------------
1           070147     1           MONSO003             1
2           070147     2           MONSO003             1
3           070147     3           MONSO003             2
4           070147     4           MONSO003             2
5           070147     5           MONSO003             3
6           070147     6           MONGR025             1
7           070147     7           VERSA008             1
8           070147     8           LAGER                1
9           912001     1           MONGR025             1
10          912001     2           VERSA008             1
11          912001     3           VERSA008             1

<强>解释

DENSE_RANK() - 窗口函数的工作方式类似于内联GROUP BY语句;上面的代码通过'MATERIAL'和'WORKCENTER'和'NEW_OPR_SEQ%2'将您的行拆分成组(见PARTITION BY部分)。使用“NEW_OPR_SEQ”列提供的订单(请参阅ORDER BY)将每个组中的记录编号为1到n

NEW_OPR_SEQ % 2 - 是让整个事情发挥作用的伎俩。该代码返回整数除以2的余数,即0表示偶数,1表示奇数。本质上,这段代码将你的行分成偶数编号和奇数编号。

如果要返回0,其中记录没有匹配的记录,则可以使用COUNT()函数,如下所示:

SELECT *,
    CASE WHEN COUNT(*) OVER( PARTITION BY MATERIAL, WORKCENTER, GroupNumber ) = 1 THEN 0
        ELSE GroupNumber
    END AS GroupNumberOrZero
FROM (
    SELECT *,
        DENSE_RANK() OVER( PARTITION BY MATERIAL, WORKCENTER, NEW_OPR_SEQ % 2 ORDER BY NEW_OPR_SEQ ) AS GroupNumber
    FROM #Data ) AS Ranked
ORDER BY ID

输出:

ID          MATERIAL   NEW_OPR_SEQ WORKCENTER           GroupNumber          GroupNumberOrZero
----------- ---------- ----------- -------------------- -------------------- --------------------
1           070147     1           MONSO003             1                    1
2           070147     2           MONSO003             1                    1
3           070147     3           MONSO003             2                    2
4           070147     4           MONSO003             2                    2
5           070147     5           MONSO003             3                    0
6           070147     6           MONGR025             1                    0
7           070147     7           VERSA008             1                    0
8           070147     8           LAGER                1                    0
9           912001     1           MONGR025             1                    0
10          912001     2           VERSA008             1                    1
11          912001     3           VERSA008             1                    1