先数后归并在一起

时间:2019-04-08 06:02:11

标签: sql sql-server

我希望有人给我一个建议。

假设我有这样的数据:

    Ref No      Whatever      Seq      Value
    A           Bla bla…      1        1 
    A           Bla bla…      2        1
    A           Bla bla…      3        0
    A           Bla bla…      4        1
    B           Bla bla…      5        0
    B           Bla bla…      6        1
    B           Bla bla…      7        0
    B           Bla bla…      8        1
    B           Bla bla…      9        0

我如何使用SQL来获得类似的信息?

    Ref No      Whatever      Value      Total
    A           Bla bla…      0          2
    B           Bla bla…      0          0
    B           Bla bla…      0          1
    B           Bla bla…      0          1

基本上尝试基于Value = 0进行过滤,并在基于Seq排序之前对记录数进行计数。

谢谢。

2 个答案:

答案 0 :(得分:1)

您可以尝试以下方法:

WITH
    [CTE1] AS
    (
        SELECT [Seq] AS [Val0Seq], [RefNo], [Seq], [Value]
        FROM @Data
        WHERE [Value] = 0
    UNION ALL
        SELECT C.[Val0Seq], D.[RefNo], D.[Seq], D.[Value]
        FROM @Data AS D INNER JOIN [CTE1] AS C ON C.[RefNo] = D.[RefNo] AND C.[Seq] = D.[Seq] + 1
        WHERE D.[Value] <> 0
    ),
    [CTE2] AS
    (
        SELECT MAX([Seq]) AS [Seq], COUNT(*) - 1 AS [Count]
        FROM [CTE1]
        GROUP BY [Val0Seq]
    )
SELECT D.[RefNo], D.[Whatever], D.[Value], C.[Count]
FROM @Data AS D INNER JOIN [CTE2] AS C ON C.[Seq] = D.[Seq]

第一个公用表表达式([CTE1])是递归的。我将分别解释这两个部分。

SELECT的anchor语句(在UNION ALL之前的[CTE1]会选择所有值为0的记录。这就是我的出发点。我为该记录分配一个唯一值[Val0Seq],与[Seq]值相对应。 这将导致以下结果:

Val0Seq      Ref No      Seq      Value
3            A           3        0
5            B           5        0
7            B           7        0
9            B           9        0

SELECT的递归语句(在{{1}之后的UNION ALL),只要其值不为0并且它们的[ RefNo]值相等。 [CTE1]的全部结果如下:

CTE1

第二个公用表表达式(Val0Seq Ref No Seq Value 3 A 1 1 3 A 2 1 3 A 3 0 5 B 5 0 7 B 6 1 7 B 7 0 9 B 8 1 9 B 9 0 )将[CTE2]的数据按[CTE1]进行分组,因为这些组包含我需要的信息。对于每个组,我选择最大的[Val0Seq]值(因为它是该值为0的起始记录),并且该组中的记录数为1(因为我不想将该起始记录包括在计数中)结果)。 [Seq]的这种逻辑产生以下数据:

[CTE2]

最终(主)查询仅将[Seq] [Count] 3 2 5 0 7 1 9 1 的结果返回到原始数据(在字段[CTE2]上)并显示最终结果:

[Seq]

答案 1 :(得分:0)

使用条件聚合创建记录组,我想到了这个解决方案。

首先,创建并填充示例表(在您将来的问题中为我们保存此步骤)

DECLARE @T AS TABLE
(
    RefNo char(1),
    Whatever varchar(10),
    Seq int,
    [Value] int
)


INSERT INTO @T (RefNo, Whatever, Seq, [Value]) VALUES
('A', 'Bla bla…', 1, 1), 
('A', 'Bla bla…', 2, 1),
('A', 'Bla bla…', 3, 0),
('A', 'Bla bla…', 4, 1),
('B', 'Bla bla…', 5, 0),
('B', 'Bla bla…', 6, 1),
('B', 'Bla bla…', 7, 0),
('B', 'Bla bla…', 8, 1),
('B', 'Bla bla…', 9, 0);

然后是创建组的常用表表达式:

WITH CTE AS
(
    SELECT  RefNo, 
            Whatever, 
            Seq, 
            [Value],
            SUM(IIF([Value] = 0, 1, 0)) OVER(ORDER BY Seq) As Grp
    FROM @T
)

查询:

SELECT  RefNo, 
        Whatever, 
        [Value], 
        (
            SELECT COUNT(*) 
            FROM CTE AS T1 
            WHERE T1.Grp = T0.Grp -1
            AND T1.[Value] <> 0
            AND T1.RefNo = T0.RefNo
        ) As [Count]
FROM CTE As T0
WHERE [Value] = 0

结果:

RefNo   Whatever    Value   Count
A       Bla bla…    0       2
B       Bla bla…    0       0
B       Bla bla…    0       1
B       Bla bla…    0       1