使用Group by子句后获取重复的值

时间:2018-09-21 16:15:49

标签: sql sql-server tsql

我有一张这样的桌子:

+------------+---------------+--------------------------+---------+
| GeneralKey |     Label     |         Extended         | OrderID |
+------------+---------------+--------------------------+---------+
|         63 | Take-Off      | Project Status           |       1 |
|         64 | Hold          | Project Status           |       3 |
|         65 | Pending       | Project Status           |       5 |
|         66 | Contracted    | Project Status           |       6 |
|         67 | Dead          | Project Status           |       7 |
|         86 | Pricing       | Project Status           |       4 |
|         99 | Bid Request   | Project Status           |       0 |
|        100 | Take-Off      | Design Contracted Status |       0 |
|        101 | Hold          | Design Contracted Status |       2 |
|        102 | Pricing       | Design Contracted Status |       3 |
|        103 | Issued        | Design Contracted Status |       4 |
|        104 | In-House      | Design Contracted Status |       5 |
|        105 | Shops/layouts | Project Status           |       2 |
|        106 | Shops/layouts | Design Contracted Status |       1 |
+------------+---------------+--------------------------+---------+

我已经存储了要使用该表的存储过程,例如:

BEGIN

        DECLARE @Parameter1 VARCHAR(50)
        DECLARE @Parameter2 VARCHAR(50);
        ;WITH CTE
            AS (SELECT
                    *
                   , ROW_NUMBER() OVER(ORDER BY
                                          (SELECT
                                                NULL
                                          )) AS [rn]
                    FROM STRING_SPLIT(@Extended , ','))
            SELECT
                 @Parameter1 = MAX(CASE
                                   WHEN [rn] = 1
                                   THEN VALUE
                                END)
                , @Parameter2 = MAX(CASE
                                   WHEN [rn] = 2
                                   THEN VALUE
                                END)
                 FROM [CTE]

        SELECT
             [GeneralKey]
            , [Label]
             FROM [General]
             WHERE [Extended] = (SELECT
                                   @Parameter1)
                  OR [Extended] = (SELECT
                                     @Parameter2)
             GROUP BY
                    [Label]
                   ,[GeneralKey]
                   , [OrderID]
             ORDER BY
                    [OrderID];
    END

问题是当我使用exec指令执行它

usp_Get_StatusListByDesignType @Extended = 'Project Status,Design Contracted Status'

它返回重复的Label值:

+------------+---------------+
| GeneralKey |     Label     |
+------------+---------------+
|         99 | Bid Request   |
|        100 | Take-Off      |
|         63 | Take-Off      |
|        106 | Shops/layouts |
|        105 | Shops/layouts |
|        101 | Hold          |
|        102 | Pricing       |
|         64 | Hold          |
|        103 | Issued        |
|         86 | Pricing       |
|        104 | In-House      |
|         65 | Pending       |
|         66 | Contracted    |
|         67 | Dead          |
+------------+---------------+

您可以看到我有重复的值(Label),GROUP BY子句不适用于存储过程。我究竟做错了什么?问候

更新

在下面的评论中,我尝试将GeneralKey包含在聚合函数中,例如:

 SELECT
                 SUM([GeneralKey])
                , [Label]
                 FROM [General]
                 WHERE [Extended] IN (@Parameter1, @Parameter2)
                GROUP BY 
                [Label]
                ,[OrderID]
                 ORDER BY
                        [OrderID];

但是我得到相同的结果

2 个答案:

答案 0 :(得分:2)

您添加到GROUP BY的任何字段都是结果集将要汇总到的字段。如果这些字段之一比您想要的更细,则必须将其从组中删除,否则结果集将采用该粒度。

在您的情况下(您的最后一次尝试),您的GROUP BY中有OrderID。因为每个OrderID都有多个Label,所以当您希望结果集位于OrderID的粒度时,结果集将处于Label的粒度。

一个简单的查询即可执行您想要的操作:

SELECT SUM(GeneralKey)
    ,Label
FROM General
WHERE Extended IN (
        @Parameter1
        ,@Parameter2
        )
GROUP BY Label;

如果您需要OrderID参与其中(可能是为了订购),则需要通过它进行汇总:

SELECT SUM(GeneralKey)
    ,Label
FROM General
WHERE Extended IN (
        @Parameter1
        ,@Parameter2
        )
GROUP BY Label
ORDER BY MAX(OrderId)

ORDER BY是RDBMS处理数据时要执行的最后步骤之一。它发生在GROUP BY之后,因此,如果该字段的粒度级别比结果集中所需的粒度级别更高,则您必须告诉它如何汇总ORDER BY所需的字段。

答案 1 :(得分:0)

这是将逗号分隔的匹配项列表导出到计算字段中的方法。

DECLARE @T TABLE(GeneralKey INT, Label NVARCHAR(50), OrderID INT, Extended NVARCHAR(50))
INSERT @T VALUES (99,'Bid-Request',1,'Project Status'),(100,'Take-Off',3,'Project Status'),(63,'Bid-Request',5,'Project Status'),(199,'Bid-Request',10,'Design Contracted Status')

DECLARE @Extended NVARCHAR(50) = 'Project Status,Design Contracted Status'

DECLARE @Parameter1 VARCHAR(50) ='Project Status'
DECLARE @Parameter2 VARCHAR(50) = 'Design Contracted Status'

SELECT
    T.Label,
    MInOrderId = MIN(OrderID),
    MaxOrderID = MAX(OrderID),
    GeneralKeys=
        STUFF((
            SELECT ', ' + CONVERT(VARCHAR(10), GeneralKey)
            FROM @T This WHERE This.Label = T.Label AND This.Extended IN(@Parameter1,@Parameter2)
            FOR XML PATH ('')) , 1, 1, ''),
    OrderIds=
        STUFF((
            SELECT ', ' + CONVERT(VARCHAR(10), OrderID)
            FROM @T This WHERE This.Label = T.Label AND This.Extended IN(@Parameter1,@Parameter2)
            FOR XML PATH ('')) , 1, 1, ''),      
    ExtendedIds=
        STUFF((
            SELECT DISTINCT ', ' +  Extended
            FROM @T This WHERE This.Label = T.Label AND This.Extended IN(@Parameter1,@Parameter2)
            FOR XML PATH ('')) , 1, 1, '')   
FROM 
    @T T
WHERE 
    Extended IN (@Parameter1,@Parameter2)
GROUP BY
    T.Label
ORDER BY
   MIN(OrderID)