【问题标题】:SQL Server : combining like rowsSQL Server:组合类似的行
【发布时间】:2014-06-06 17:25:58
【问题描述】:

我有以下疑问:

SELECT DISTINCT [WL].[Id]
  ,[WL].[UserId]
  ,[WL].[DIF]
  ,[WL].[MW]
  ,[WL].[Notes]
  ,[WL].[WDate]
  ,[WL].[CB]
  ,[WL].[MPH] 
  ,[U].[Id]
  ,[U].[UserName]
  ,[U].[We]
  ,[U].[SLength]
  ,[U].[UP]
  ,[U].[PU]
  ,[U].[ANumber]
  ,[U].[G_CK]
FROM 
    [Wsite].[dbo].[WLog] as WL 
INNER JOIN 
    [Wsite].[dbo].[Users] AS U ON [U].[Id] = [WL].[UserId] 
WHERE 
    [WL].[WDate] >= CONVERT(datetime, '2012-01-01 00:00:00', 120)  
    AND [WL].[WDate] <= CONVERT(datetime, GETDATE(), 120)
GROUP BY 
    [WL].[UserId]

我得到的错误是:

选择中的列“Wsite.dbo.WLog.Id”无效 列表,因为它既不包含在聚合函数中,也不包含在聚合函数中 GROUP BY 子句。

如果列表中有多个UserID,我想要的只是合并数据。

举个例子:

Id  | UserId | .... | Id   | UserName    | SLength | ....
5843| 99304  | .... | 99304| Bob Barker  | 14      | ....
5844| 06300  | .... | 06300| Dean Martin | 104     | ....
5845| 99304  | .... | 99304| Bob Barker  | 8       | ....
5846| 99304  | .... | 99304| Bob Barker  | 11      | ....
5847| 7699   | .... | 7699 | John Doe    | 0       | ....

所以它应该是这样的:

Id  | UserId | .... | Id   | UserName    | SLength | ....
5843| 99304  | .... | 99304| Bob Barker  | 33      | ....
5844| 06300  | .... | 06300| Dean Martin | 104     | ....
5847| 7699   | .... | 7699 | John Doe    | 0       | ....

请注意,Bob Barker 的 SLength 已合并 (14+8+11=33)。

任何帮助都会很棒!谢谢!

更新

SELECT DISTINCT 
   MIN([WL].[Id]) AS [WLID]
  ,MIN([WL].[UserId]) AS [WLUD]
  ,SUM([WL].[DIF]) AS [DIF]
  ,SUM([WL].[MW]) AS [MW]
  ,[WL].[Notes]
  ,[WL].[WDate]
  ,SUM([WL].[CB]) AS [CB]
  ,SUM([WL].[MPH])  AS [MPH]
  ,MIN([U].[Id] AS [UID]
  ,MIN([U].[UserName] AS [UUserName]
  ,[U].[We]
  ,SUM([U].[SL]) AS [SL]
  ,[U].[UP]
  ,[U].[PU]
  ,[U].[ANumber]
  ,[U].[G_CK]
  FROM [Wsite].[dbo].WLog as WL 
INNER JOIN [Wsite].[dbo].[Users] AS U 
    ON [U].[Id] = [WL].[UserId] 
 WHERE [WL].[WDate] >= CONVERT(datetime, '2012-01-01 00:00:00', 120)  
   AND [WL].[WDate] <= CONVERT(datetime, GETDATE(), 120)
GROUP BY 
   [WL].[Notes]
  ,[WL].[WDate]
  ,[U].[We]
  ,[U].[UP]
  ,[U].[PU]
  ,[U].[ANumber]
  ,[U].[G_CK]
ORDER BY [U].[UserName] DESC

【问题讨论】:

  • 除了Id 字段和SLength 字段之外,所有其他字段是否都将包含相同的数据?

标签: sql sql-server sql-server-2008 group-by inner-join


【解决方案1】:

当您使用 GROUP BY 时,这意味着您想要将相似的元素组合在一起,并呈现您想要显示的剩余项目的某种聚合(COUNT、SUM、MIN 等)。因此,如果您在选择列表中包含 [WL].[Id],您基本上将获得完整的选择而无需任何聚合(因为 [WL].[Id] 是唯一的)。

您需要执行以下操作:

SELECT MIN([WL].[Id]) AS ID
  ,[WL].[UserId]
  ,[U].[Id]
  ,[U].[UserName]
  ,SUM([SLength]) AS SLength
FROM [Wsite].[dbo].[WLog] as WL 
INNER JOIN [Wsite].[dbo].[Users] AS U 
        ON [U].[Id] = [WL].[UserId] 
     WHERE [WL].[WDate] >= CONVERT(datetime, '2012-01-01 00:00:00', 120)  
       AND [WL].[WDate] <= CONVERT(datetime, GETDATE(), 120)
  GROUP BY [WL].[UserId]
  ,[U].[Id]
  ,[U].[UserName]

(为简洁起见,我没有包括所有字段)。

还请注意,由于 [WL].[Id] 似乎是唯一的,因此在这种情况下它是没有意义的,除非您想显示它的第一次出现(然后您可以将 MIN([WL].[Id]) 添加到SELECT 列表)。

【讨论】:

  • 这似乎没有将它们结合起来?
  • 哪个不结合什么在哪里?请提供详细信息。
  • 用户名仍然不止一次出现。它没有组合在一起。
  • 请添加您更新的查询 - 很可能您包含一个唯一字段(如 [WL].[Id]),它将抑制聚合。请参阅我的答案注释。
  • 再次阅读我关于 [WL].[Id] 的说明。如果您将其包含在选择列表中,您将无法获得所需的分组。要么将其从列表中删除,要么使用其值的聚合函数。需要明确的是,SELECT 列表(非聚合字段)是在数据中重复的那些字段。从您显示的数据来看,[WL].[Id] 似乎是唯一值。我更新了我的答案以包含 [WL].[Id] 和 MIN 聚合。
【解决方案2】:

不确定,但这可能适用于您的情况。

SELECT DISTINCT [WL].[Id]
  ,[WL].[UserId]
  ,[WL].[DIF]
  ,[WL].[MW]
  ,[WL].[Notes]
  ,[WL].[WDate]
  ,[WL].[CB]
  ,[WL].[MPH] 
  ,[U].[Id]
  ,[U].[UserName]
  ,[U].[We]
  ,SUM([U].[SLength]) OVER (PARTITION BY [WL].[UserId])
  ,[U].[UP]
  ,[U].[PU]
  ,[U].[ANumber]
  ,[U].[G_CK]
          FROM [Wsite].[dbo].[WLog] as WL 
    INNER JOIN [Wsite].[dbo].[Users] AS U 
            ON [U].[Id] = [WL].[UserId] 
         WHERE [WL].[WDate] >= CONVERT(datetime, '2012-01-01 00:00:00', 120)  
           AND [WL].[WDate] <= CONVERT(datetime, GETDATE(), 120)

【讨论】:

    【解决方案3】:

    如果您使用GROUP BY,则必须以某种方式聚合不在分组中的任何列(SUMMINMAX 等)

    试试这个:

    SELECT 
       [WL].[Id]
      ,[WL].[UserId]
      ,[WL].[DIF]
      ,[WL].[MW]
      ,[WL].[Notes]
      ,[WL].[WDate]
      ,[WL].[CB]
      ,[WL].[MPH] 
      ,Sum ([U].[SLength]) SLength
    FROM [Wsite].[dbo].[WLog] as WL 
    INNER JOIN [Wsite].[dbo].[Users] AS U 
        ON [U].[Id] = [WL].[UserId] 
    WHERE [WL].[WDate] >= CONVERT(datetime, '2012-01-01 00:00:00', 120)  
        AND [WL].[WDate] <= CONVERT(datetime, GETDATE(), 120)
    GROUP BY 
       [WL].[Id]
      ,[WL].[UserId]
      ,[WL].[DIF]
      ,[WL].[MW]
      ,[WL].[Notes]
      ,[WL].[WDate]
      ,[WL].[CB]
      ,[WL].[MPH] 
    

    以下是您可以使用的聚合函数:

    http://msdn.microsoft.com/en-us/library/ms173454.aspx

    【讨论】:

    • 就像@Dave Jemiison 一样,用户名仍然不止一次出现。它没有组合在一起
    • 我取出了一些列并编辑了查询。试试看。
    【解决方案4】:

    您对GROUP BY 的使用不正确。 SELECT 中使用的所有列都应该在 GROUP BY 子句中或者应该是聚合函数。
    您的查询应该如下所示。

    SELECT DISTINCT MIN([WL].[Id]) [Id]
        ,[WL].[UserId]
        ,[WL].[DIF]
        ,[WL].[MW]
        ,[WL].[Notes]
        ,[WL].[WDate]
        ,[WL].[CB]
        ,[WL].[MPH] 
        ,[U].[Id]
        ,[U].[UserName]
        ,[U].[We]
        ,SUM([U].[SLength]) SLength
        ,[U].[UP]
        ,[U].[PU]
        ,[U].[ANumber]
        ,[U].[G_CK]
    FROM [Wsite].[dbo].[WLog] as WL 
        INNER JOIN [Wsite].[dbo].[Users] AS U 
            ON [U].[Id] = [WL].[UserId] 
    WHERE [WL].[WDate] >= CONVERT(datetime, '2012-01-01 00:00:00', 120)  
           AND [WL].[WDate] <= CONVERT(datetime, GETDATE(), 120)
    GROUP BY [WL].[UserId]
        ,[WL].[DIF]
        ,[WL].[MW]
        ,[WL].[Notes]
        ,[WL].[WDate]
        ,[WL].[CB]
        ,[WL].[MPH] 
        ,[U].[Id]
        ,[U].[UserName]
        ,[U].[We]
        ,[U].[UP]
        ,[U].[PU]
        ,[U].[ANumber]
        ,[U].[G_CK]
    

    【讨论】:

    • 看起来[WL].[Id]是一个身份字段,所以在选择列表中包含会导致所有结果显示不聚合。
    • @DaveJemison 谢谢,已修复。
    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多