从表中选择多个列,但逐个分组

Oza*_*ten 39 sql group-by

表名是"OrderDetails",列如下:

OrderDetailID || ProductID || ProductName || OrderQuantity
Run Code Online (Sandbox Code Playgroud)

我正在尝试选择多个列和Group By ProductID,同时具有OrderQuantity的SUM.

 Select ProductID,ProductName,OrderQuantity Sum(OrderQuantity)
 from OrderDetails Group By ProductID
Run Code Online (Sandbox Code Playgroud)

但是这个代码当然会出错.我必须添加其他列名称分组,但这不是我想要的,因为我的数据有很多项目,所以结果是出乎意料的.

示例数据查询:

OrderDetails中的ProductID,ProductName,OrderQuantity

结果如下:

 ProductID     ProductName    OrderQuantity
    1001          abc               5
    1002          abc               23    (ProductNames can be same)
    2002          xyz               8
    3004          ytp               15
    4001          aze               19
    1001          abc               7     (2nd row of same ProductID)
Run Code Online (Sandbox Code Playgroud)

预期结果:

 ProductID     ProductName    OrderQuantity
    1001          abc               12    (group by productID while summing)
    1002          abc               23
    2002          xyz               8
    3004          ytp               15
    4001          aze               19
Run Code Online (Sandbox Code Playgroud)

如何选择多列和Group By ProductID列,因为ProductName不是唯一的?

在这样做的同时,也获得OrderQuantity列的总和.

小智 73

当我有多列选择时,我使用此技巧分组一列:

SELECT MAX(id) AS id,
    Nume,
    MAX(intrare) AS intrare,
    MAX(iesire) AS iesire,
    MAX(intrare-iesire) AS stoc,
    MAX(data) AS data
FROM Produse
GROUP BY Nume
ORDER BY Nume
Run Code Online (Sandbox Code Playgroud)

这有效.

  • 巧妙,谢谢!对于那些路过:你在每个未分组的列周围放置`max()`,把`as ___`重命名为你想要它显示的内容,然后`分组'你想要的那些没有的列` max()`围绕着他们. (4认同)
  • 这没有道理,而且可能是错误的!如果数据中每个column_A有多个column_B,则如果按Column_A分组并在选择中使用MAX(Column_B)绕过分组限制,则它只是这些column_B值之一(此处最大的值由MAX)。通常不是您想要的!并且,如果数据中每个column_A的column_B值没有不同,那么您应该简单地将column_B添加到GROUP BY子句中,如其他答案所述。@安德鲁 (4认同)
  • 哈哈,愚弄 SQL 的好方法,但我想知道这是否适用于所有情况? (3认同)
  • 我同意@Andrew – S.Serpooshan 当我们在列中有不同的值时它不起作用 (3认同)
  • 如果您的列类型是布尔值,这将不起作用 (2认同)

M.A*_*Ali 11

你的数据

DECLARE @OrderDetails TABLE 
(ProductID INT,ProductName VARCHAR(10), OrderQuantity INT)

INSERT INTO @OrderDetails VALUES
(1001,'abc',5),(1002,'abc',23),(2002,'xyz',8),
(3004,'ytp',15),(4001,'aze',19),(1001,'abc',7)
Run Code Online (Sandbox Code Playgroud)

询问

 Select ProductID, ProductName, Sum(OrderQuantity) AS Total
 from @OrderDetails 
 Group By ProductID, ProductName  ORDER BY ProductID
Run Code Online (Sandbox Code Playgroud)

结果

???????????????????????????????????
? ProductID ? ProductName ? Total ?
???????????????????????????????????
?      1001 ? abc         ?    12 ?
?      1002 ? abc         ?    23 ?
?      2002 ? xyz         ?     8 ?
?      3004 ? ytp         ?    15 ?
?      4001 ? aze         ?    19 ?
???????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

  • 是的,但我的问题已经尽可能明确了。如果我把它放在我的问题上,就会有太多的数据无法理解。所以这就是为什么我要求专门选择多列,而仅按一列分组。 (3认同)
  • 但我说,我不想添加其他列名称分组,它会产生意想不到的结果. (2认同)

Aiv*_*ras 6

mysql GROUP_CONCAT函数可以帮助https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_group-concat

SELECT ProductID, GROUP_CONCAT(DISTINCT ProductName) as Names, SUM(OrderQuantity)
FROM OrderDetails GROUP BY ProductID
Run Code Online (Sandbox Code Playgroud)

这将返回:

ProductID     Names          OrderQuantity
1001          red            5
1002          red,black      6
1003          orange         8
1004          black,orange   15
Run Code Online (Sandbox Code Playgroud)

与@Urs Marian 这里发布的想法类似/sf/answers/2714549421/


Hai*_*OUI 6

我只是想添加一种更有效和通用的方法来解决此类问题。主要思想是关于使用子查询。

做你的分组,并在表的 ID 上加入同一个表。

您的情况更具体,因为您的 productId不是唯一的,因此有两种方法可以解决此问题。

我将从更具体的解决方案开始:由于您的 productId不是唯一的,我们将需要一个额外的步骤,即DISCTINCT在分组和执行子查询后选择产品 ID,如下所示:

WITH CTE_TEST AS (SELECT productId, SUM(OrderQuantity) Total
                    FROM OrderDetails
                    GROUP BY productId)
SELECT DISTINCT(OrderDetails.ProductID), OrderDetails.ProductName, CTE_TEST.Total
FROM OrderDetails 
INNER JOIN CTE_TEST ON CTE_TEST.ProductID = OrderDetails.ProductID
Run Code Online (Sandbox Code Playgroud)

这完全返回了预期的结果

 ProductID     ProductName         Total
    1001          abc               12    
    1002          abc               23
    2002          xyz               8
    3004          ytp               15
    4001          aze               19
Run Code Online (Sandbox Code Playgroud)

但是有一个更干净的方法来做到这一点。我猜这ProductId是 products 表的外键,我猜这个表中应该有OrderId 主键(唯一)。

在这种情况下,只需执行几个步骤即可包含额外的列,同时仅对一个进行分组。这将是与以下相同的解决方案

我们以这张t_Value表为例:

在此处输入图片说明

如果我想按描述分组并显示所有列。

我所要做的就是:

  1. WITH CTE_Name使用您的 GroupBy 列和 COUNT 条件创建子查询
  2. 从值表中选择所有(或您想显示的任何内容)和 CTE 中的总数
  3. INNER JOIN在 ID(主键或唯一约束)列上使用 CTE

就是这样!

这是查询

WITH CTE_TEST AS (SELECT Description, MAX(Id) specID, COUNT(Description) quantity 
                    FROM sch_dta.t_value
                    GROUP BY Description)
SELECT sch_dta.t_Value.*, CTE_TEST.quantity 
FROM sch_dta.t_Value 
INNER JOIN CTE_TEST ON CTE_TEST.specID = sch_dta.t_Value.Id
Run Code Online (Sandbox Code Playgroud)

结果如下:

在此处输入图片说明