【发布时间】: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
我明白GROUP BY x的意思。
但是GROUP BY x, y 是如何工作的,它是什么意思?
【问题讨论】:
标签: sql group-by multiple-columns
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 学期”组)
希望这是有道理的。
【讨论】:
GROUP BY A,B 与GROUP BY B,A 相同?
GROUP BY a, b 和GROUP BY a AND b 之间存在差异,因为第二个只列出了内容完全相同的分组项目,没有“下组”。在这种情况下,输出将与第一个相同。
这里我不仅要解释 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;
记住这个顺序:
SELECT(用于从数据库中选择数据)
FROM(子句用于列出表格)
WHERE(子句用于过滤记录)
GROUP BY(子句可用于 SELECT 语句中以收集数据 跨多条记录并将结果按一列或多列分组)
HAVING(子句与 GROUP BY 子句结合使用 将返回的行组限制为仅符合条件的行 是真的)
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 BY、ORDER BY子句和ASC:
SELECT
customerId, COUNT(*)
FROM
Orders
GROUP BY customerId
ORDER BY COUNT(*) ASC;
使用AVG 函数结合GROUP BY 和HAVING 子句,检索平均单价大于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)
以下语句将 categoryId 和 productId 列中具有相同值的行分组:
SELECT
categoryId, categoryName, productId, SUM(unitPrice)
FROM
Products p
INNER JOIN
Categories c ON c.categoryId = p.categoryId
GROUP BY categoryId, productId
【讨论】:
用来自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场友谊赛。
注意:在这种情况下必须使用计数器列。
【讨论】: