MySQL:groupby如何处理没有聚合函数的列?

six*_*ude 8 mysql group-by

关于group by命令如何在mysql中工作,我有点困惑.

假设我有一张桌子:

mysql> select recordID, IPAddress, date, httpMethod from Log_Analysis_Records_dalhousieShort;                   
+----------+-----------------+---------------------+-------------------------------------------------+
| recordID | IPAddress       | date                | httpMethod                                      |
+----------+-----------------+---------------------+-------------------------------------------------+
|        1 | 64.68.88.22     | 2003-07-09 00:00:21 | GET /news/science/cancer.shtml HTTP/1.0         | 
|        2 | 64.68.88.166    | 2003-07-09 00:00:55 | GET /news/internet/xml.shtml HTTP/1.0           | 
|        3 | 129.173.177.214 | 2003-07-09 00:01:23 | GET / HTTP/1.1                                  | 
|        4 | 129.173.177.214 | 2003-07-09 00:01:23 | GET /include/fcs_style.css HTTP/1.1             | 
|        5 | 129.173.177.214 | 2003-07-09 00:01:23 | GET /include/main_page.css HTTP/1.1             | 
|        6 | 129.173.177.214 | 2003-07-09 00:01:23 | GET /images/bigportaltopbanner.gif HTTP/1.1     | 
|        7 | 129.173.177.214 | 2003-07-09 00:01:23 | GET /images/right_1.jpg HTTP/1.1                | 
|        8 | 64.68.88.165    | 2003-07-09 00:02:43 | GET /studentservices/responsible.shtml HTTP/1.0 | 
|        9 | 64.68.88.165    | 2003-07-09 00:02:44 | GET /news/sports/basketball.shtml HTTP/1.0      | 
|       10 | 64.68.88.34     | 2003-07-09 00:02:46 | GET /news/science/space.shtml HTTP/1.0          | 
|       11 | 129.173.159.98  | 2003-07-09 00:03:46 | GET / HTTP/1.1                                  | 
|       12 | 129.173.159.98  | 2003-07-09 00:03:46 | GET /include/fcs_style.css HTTP/1.1             | 
|       13 | 129.173.159.98  | 2003-07-09 00:03:46 | GET /include/main_page.css HTTP/1.1             | 
|       14 | 129.173.159.98  | 2003-07-09 00:03:48 | GET /images/bigportaltopbanner.gif HTTP/1.1     | 
|       15 | 129.173.159.98  | 2003-07-09 00:03:48 | GET /images/left_1g.jpg HTTP/1.1                | 
|       16 | 129.173.159.98  | 2003-07-09 00:03:48 | GET /images/webcam.gif HTTP/1.1                 | 
+----------+-----------------+---------------------+-------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

当我执行这个语句时,它如何选择recordID要包括哪个,因为有一系列的recordIDs是正确的?它只是选择匹配的第一个吗?

mysql> select recordID, IPAddress, date, httpMethod from Log_Analysis_Records_dalhousieShort GROUP BY IPADDRESS;
+----------+-----------------+---------------------+-------------------------------------------------+
| recordID | IPAddress       | date                | httpMethod                                      |
+----------+-----------------+---------------------+-------------------------------------------------+
|       11 | 129.173.159.98  | 2003-07-09 00:03:46 | GET / HTTP/1.1                                  | 
|        3 | 129.173.177.214 | 2003-07-09 00:01:23 | GET / HTTP/1.1                                  | 
|        8 | 64.68.88.165    | 2003-07-09 00:02:43 | GET /studentservices/responsible.shtml HTTP/1.0 | 
|        2 | 64.68.88.166    | 2003-07-09 00:00:55 | GET /news/internet/xml.shtml HTTP/1.0           | 
|        1 | 64.68.88.22     | 2003-07-09 00:00:21 | GET /news/science/cancer.shtml HTTP/1.0         | 
|       10 | 64.68.88.34     | 2003-07-09 00:02:46 | GET /news/science/space.shtml HTTP/1.0          | 
+----------+-----------------+---------------------+-------------------------------------------------+
6 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

对于这个表,这些max(date)min(date)值似乎对我来说是合乎逻辑的,但我对如何选择recordIDhttpMethod在哪里感到困惑.

在一个命令中使用两个聚合函数是否安全?

mysql> select recordID, IPAddress, min(date), max(date), httpMethod from Log_Analysis_Records_dalhousieShort GROUP BY IPADDRESS;
+----------+-----------------+---------------------+---------------------+-------------------------------------------------+
| recordID | IPAddress       | min(date)           | max(date)           | httpMethod                                      |
+----------+-----------------+---------------------+---------------------+-------------------------------------------------+
|       11 | 129.173.159.98  | 2003-07-09 00:03:46 | 2003-07-09 00:03:48 | GET / HTTP/1.1                                  | 
|        3 | 129.173.177.214 | 2003-07-09 00:01:23 | 2003-07-09 00:01:23 | GET / HTTP/1.1                                  | 
|        8 | 64.68.88.165    | 2003-07-09 00:02:43 | 2003-07-09 00:02:44 | GET /studentservices/responsible.shtml HTTP/1.0 | 
|        2 | 64.68.88.166    | 2003-07-09 00:00:55 | 2003-07-09 00:00:55 | GET /news/internet/xml.shtml HTTP/1.0           | 
|        1 | 64.68.88.22     | 2003-07-09 00:00:21 | 2003-07-09 00:00:21 | GET /news/science/cancer.shtml HTTP/1.0         | 
|       10 | 64.68.88.34     | 2003-07-09 00:02:46 | 2003-07-09 00:02:46 | GET /news/science/space.shtml HTTP/1.0          | 
+----------+-----------------+---------------------+---------------------+-------------------------------------------------+
6 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

And*_*eKR 13

通常在没有聚合函数的select表达式中列出字段时使用GROUP BY是无效的SQL并且应该抛出错误.

但是,MySQL允许这样做,只需随机选择一个值.尽量避免它,因为它令人困惑.

要禁止这一点,您可以在运行时说:

SET sql_mode := CONCAT('ONLY_FULL_GROUP_BY,',@@sql_mode);

或使用配置值和/或命令行选项sql-mode.

是的,列出两个聚合函数是完全有效的.

  • 需要明确的是,它实际上并不是**随机**。如果您对不变的表重复执行相同的查询,则每次都会得到相同的结果。但是更改表(即使是以在查询结果中不可见的方式)可能会导致出现不同的值。 (2认同)

小智 5

因为我显然是新手,所以我无法发布有用的图片,所以我会尝试用文字来做到这一点......

我刚刚对此进行了测试,似乎不在 GROUP BY 中的字段的值将使用与 group by 条件匹配的第一行的值。这也将解释其他人在选择不在 group by 子句中的列时所经历的感知“随机性”。

例子:

创建一个名为“test”的表,其中包含两个名为“col1”和“col2”的列,数据如下所示:

Col1 Col2
1 2
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3

然后运行以下查询:

通过 col2 desc
从测试
顺序中选择 col1,col2

你会得到这样的结果:

1 3
2 3
3 3
1 2
1 2
2 2
3 2
2 1
3 1

现在考虑以下查询:

select groupTable.col1,groupTable.col2
from (
   select col1,col2
   from test
   order by col2 desc
) groupTable
group by groupTable.col1
order by groupTable.col1 desc

你会得到这样的结果:

3 3
2 3
1 3

将子查询更改为 asc:

按 col2 asc
从测试
顺序中选择 col1,col2

结果:

2 1
3 1
1 2
1 2
2 2
3 2
1 3
2 3
3 3

再次使用它作为子查询的基础:

select groupTable.col1,groupTable.col2
from (
   select col1,col2
   from test
   order by col2 asc
) groupTable
group by groupTable.col1
order by groupTable.col1 desc

结果:
3 1
2 1
1 2

现在您应该能够看到子查询的顺序如何影响为已选择但不在 group by 子句中的字段选择哪些值。这将解释其他人提到的感知“随机性”,因为如果子查询(或缺少)没有与 ORDER BY 子句结合,那么 mysql 将在行出现时抓取它们,但是通过在子查询中定义排序顺序,您能够控制这种行为并获得可预测的结果。