【问题标题】:Using group by on multiple columns在多列上使用 group by
【发布时间】:2011-01-26 03:44:47
【问题描述】:

我明白GROUP BY x的意思。

但是GROUP BY x, y 是如何工作的,它是什么意思?

【问题讨论】:

  • 您不会发现它被描述为这个问题所提出的。 GROUP BY 子句可以采用一个或多个字段。按客户分组;按姓氏、名字分组; GROUP BY year, store, sku etc.

标签: sql group-by multiple-columns


【解决方案1】:

Group By X 表示将所有具有相同 X 值的人放在一个组中

Group By X, Y 表示将所有 X 和 Y 值相同的人放在一个组中

为了举例说明,假设我们有下表,与谁在大学就读什么科目有关:

Table: Subject_Selection

+---------+----------+----------+
| Subject | Semester | Attendee |
+---------+----------+----------+
| ITB001  |        1 | John     |
| ITB001  |        1 | Bob      |
| ITB001  |        1 | Mickey   |
| ITB001  |        2 | Jenny    |
| ITB001  |        2 | James    |
| MKB114  |        1 | John     |
| MKB114  |        1 | Erica    |
+---------+----------+----------+

当您仅在主题列上使用group by 时;说:

select Subject, Count(*)
from Subject_Selection
group by Subject

你会得到类似的东西:

+---------+-------+
| Subject | Count |
+---------+-------+
| ITB001  |     5 |
| MKB114  |     2 |
+---------+-------+

...因为 ITB001 有 5 个条目,MKB114 有 2 个条目

如果我们要group by 两列:

select Subject, Semester, Count(*)
from Subject_Selection
group by Subject, Semester

我们会得到这个:

+---------+----------+-------+
| Subject | Semester | Count |
+---------+----------+-------+
| ITB001  |        1 |     3 |
| ITB001  |        2 |     2 |
| MKB114  |        1 |     2 |
+---------+----------+-------+

这是因为,当我们按两列分组时,就是说“将它们分组,使所有具有相同主题和学期的人都在同一组中,然后计算所有聚合函数(计数、总和、平均值等)每个组”。在这个例子中,当我们计算他们时,第一学期有 三个 人在做 ITB001,第二学期有 两个 人在做这件事。做 MKB114 的人在第 1 学期,所以没有第 2 学期的行(没有数据适合“MKB114,第 2 学期”组)

希望这是有道理的。

【讨论】:

  • @Smashery:那么这是否也意味着GROUP BY A,BGROUP BY B,A 相同?
  • 是的,确实如此。我不能确定它们是否彼此一样有效,但它们会给出相同的结果,是的。
  • 这里应该补充一点,GROUP BY a, bGROUP BY a AND b 之间存在差异,因为第二个只列出了内容完全相同的分组项目,没有“下组”。在这种情况下,输出将与第一个相同。
  • 我想补充一点,您按列分组的顺序无关紧要。在上述按学期分组的示例中,主题会给出相同的结果
  • 好吧,按 a、b 和按 b 分组,a 不会返回相同的结果 - 行以不同的顺序显示
【解决方案2】:

这里我不仅要解释 GROUP 子句的使用,还要解释 Aggregate 函数的使用。

GROUP BY 子句与聚合函数结合使用,以按一列或多列对结果集进行分组。例如:

-- GROUP BY with one parameter:
SELECT column_name, AGGREGATE_FUNCTION(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;

-- GROUP BY with two parameters:
SELECT
    column_name1,
    column_name2,
    AGGREGATE_FUNCTION(column_name3)
FROM
    table_name
GROUP BY
    column_name1,
    column_name2;

记住这个顺序:

  1. SELECT(用于从数据库中选择数据)

  2. FROM(子句用于列出表格)

  3. WHERE(子句用于过滤记录)

  4. GROUP BY(子句可用于 SELECT 语句中以收集数据 跨多条记录并将结果按一列或多列分组)

  5. HAVING(子句与 GROUP BY 子句结合使用 将返回的行组限制为仅符合条件的行 是真的)

  6. ORDER BY(关键字用于对结果集进行排序)

如果你使用聚合函数,你可以使用所有这些,这是它们必须设置的顺序,否则会出错。

聚合函数是:

MIN() 返回给定列中的最小值

MAX() 返回给定列中的最大值。

SUM() 返回给定列中数值的总和

AVG() 返回给定列的平均值

COUNT() 返回给定列中值的总数

COUNT(*) 返回表中的行数

关于使用聚合函数的 SQL 脚本示例:

假设我们需要查找总销售额大于 950 美元的销售订单。我们结合HAVING 子句和GROUP BY 子句来完成此操作:

SELECT 
    orderId, SUM(unitPrice * qty) Total
FROM
    OrderDetails
GROUP BY orderId
HAVING Total > 950;

计算所有订单并将它们分组 customerID 并对结果进行升序排序。我们结合COUNT函数和GROUP BYORDER BY子句和ASC

SELECT 
    customerId, COUNT(*)
FROM
    Orders
GROUP BY customerId
ORDER BY COUNT(*) ASC;

使用AVG 函数结合GROUP BYHAVING 子句,检索平均单价大于10 美元的类别:

SELECT 
    categoryName, AVG(unitPrice)
FROM
    Products p
INNER JOIN
    Categories c ON c.categoryId = p.categoryId
GROUP BY categoryName
HAVING AVG(unitPrice) > 10;

在子查询中使用MIN 函数按每个类别获取较便宜的产品:

SELECT categoryId,
       productId,
       productName,
       unitPrice
FROM Products p1
WHERE unitPrice = (
                SELECT MIN(unitPrice)
                FROM Products p2
                WHERE p2.categoryId = p1.categoryId)

下面将向您展示如何在子查询中使用MAX 函数来选择最近的日期项productDate”:

SELECT categoryId,
       productId,
       productName,
       unitPrice,
       productDate
FROM Products p1
WHERE productDate= (
                  SELECT MAX(productDate) 
                  FROM Products p2
                  WHERE p2.categoryId = p1.categoryId)

以下语句将 categoryIdproductId 列中具有相同值的行分组:

SELECT 
    categoryId, categoryName, productId, SUM(unitPrice)
FROM
    Products p
INNER JOIN
    Categories c ON c.categoryId = p.categoryId
GROUP BY categoryId, productId

【讨论】:

  • 但是我们将 2 列放在哪里,如何基于 2 列/更多列进行聚合是个问题
  • 这甚至不能远程回答问题......这里的问题是如何同时实现“主题”和“学期”的“链式分组”,如给定示例中所述...
  • 最后一个示例向您展示了如何使用聚合函数放置 2 列。 @ChaitanyaBapat
【解决方案3】:

用来自GROUP BY 的简单英语和两个参数,我们正在做的是寻找相似的值对并将计数添加到第 3 列。

请查看以下示例以供参考。这里我使用International football results from 1872 to 2020

+----------+----------------+--------+---+---+--------+---------+-------------------+-----+
|       _c0|             _c1|     _c2|_c3|_c4|     _c5|      _c6|                _c7|  _c8|
+----------+----------------+--------+---+---+--------+---------+-------------------+-----+
|1872-11-30|        Scotland| England|  0|  0|Friendly|  Glasgow|           Scotland|FALSE|
|1873-03-08|         England|Scotland|  4|  2|Friendly|   London|            England|FALSE|
|1874-03-07|        Scotland| England|  2|  1|Friendly|  Glasgow|           Scotland|FALSE|
|1875-03-06|         England|Scotland|  2|  2|Friendly|   London|            England|FALSE|
|1876-03-04|        Scotland| England|  3|  0|Friendly|  Glasgow|           Scotland|FALSE|
|1876-03-25|        Scotland|   Wales|  4|  0|Friendly|  Glasgow|           Scotland|FALSE|
|1877-03-03|         England|Scotland|  1|  3|Friendly|   London|            England|FALSE|
|1877-03-05|           Wales|Scotland|  0|  2|Friendly|  Wrexham|              Wales|FALSE|
|1878-03-02|        Scotland| England|  7|  2|Friendly|  Glasgow|           Scotland|FALSE|
|1878-03-23|        Scotland|   Wales|  9|  0|Friendly|  Glasgow|           Scotland|FALSE|
|1879-01-18|         England|   Wales|  2|  1|Friendly|   London|            England|FALSE|
|1879-04-05|         England|Scotland|  5|  4|Friendly|   London|            England|FALSE|
|1879-04-07|           Wales|Scotland|  0|  3|Friendly|  Wrexham|              Wales|FALSE|
|1880-03-13|        Scotland| England|  5|  4|Friendly|  Glasgow|           Scotland|FALSE|
|1880-03-15|           Wales| England|  2|  3|Friendly|  Wrexham|              Wales|FALSE|
|1880-03-27|        Scotland|   Wales|  5|  1|Friendly|  Glasgow|           Scotland|FALSE|
|1881-02-26|         England|   Wales|  0|  1|Friendly|Blackburn|            England|FALSE|
|1881-03-12|         England|Scotland|  1|  6|Friendly|   London|            England|FALSE|
|1881-03-14|           Wales|Scotland|  1|  5|Friendly|  Wrexham|              Wales|FALSE|
|1882-02-18|Northern Ireland| England|  0| 13|Friendly|  Belfast|Republic of Ireland|FALSE|
+----------+----------------+--------+---+---+--------+---------+-------------------+-----+

现在我将通过GROUP BY 操作按相似国家(列_c7)和锦标赛(_c5)值对分组,

SELECT `_c5`,`_c7`,count(*)  FROM res GROUP BY `_c5`,`_c7`

+--------------------+-------------------+--------+
|                 _c5|                _c7|count(1)|
+--------------------+-------------------+--------+
|            Friendly|  Southern Rhodesia|      11|
|            Friendly|            Ecuador|      68|
|African Cup of Na...|           Ethiopia|      41|
|Gold Cup qualific...|Trinidad and Tobago|       9|
|AFC Asian Cup qua...|             Bhutan|       7|
|African Nations C...|              Gabon|       2|
|            Friendly|           China PR|     170|
|FIFA World Cup qu...|             Israel|      59|
|FIFA World Cup qu...|              Japan|      61|
|UEFA Euro qualifi...|            Romania|      62|
|AFC Asian Cup qua...|              Macau|       9|
|            Friendly|        South Sudan|       1|
|CONCACAF Nations ...|           Suriname|       3|
|         Copa Newton|          Argentina|      12|
|            Friendly|        Philippines|      38|
|FIFA World Cup qu...|              Chile|      68|
|African Cup of Na...|         Madagascar|      29|
|FIFA World Cup qu...|       Burkina Faso|      30|
| UEFA Nations League|            Denmark|       4|
|        Atlantic Cup|           Paraguay|       2|
+--------------------+-------------------+--------+

说明:第一行的意思是南罗得西亚一共举办了11场友谊赛。

注意:在这种情况下必须使用计数器列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    • 2011-10-21
    • 1970-01-01
    • 2016-06-08
    • 2014-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多