MySQL: Как работает groupby для столбцов без агрегатных функций? - PullRequest
8 голосов
/ 14 ноября 2010

Я немного озадачен тем, как команда 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                 | 
+----------+-----------------+---------------------+-------------------------------------------------+

Когда я выполняю этот оператор, как он выбирает, какой recordID включить, поскольку существует диапазон recordID с, который будет правильным? Это просто выбирает первый, который соответствует?

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)

Для этой таблицы значения max(date) и min(date) кажутся мне логичными, но я не совсем понимаю, как recordID и httpMethod выбраны.

Безопасно ли использовать две агрегатные функции в одной команде?

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)

Ответы [ 4 ]

13 голосов
/ 14 ноября 2010

Обычно использование GROUP BY при перечислении поля в выражении выбора без агрегатной функции является недопустимым SQL и должно выдавать ошибку.

Однако MySQL допускает это и просто выбирает одно значение случайным образом.Попытайтесь избежать этого, потому что это сбивает с толку.

Чтобы запретить это, вы можете сказать во время выполнения:

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

или использовать значение конфигурации и / или командуопция строки sql-mode.

Да, перечисление двух агрегатных функций полностью допустимо.

4 голосов
/ 17 июля 2012

Поскольку я новичок, очевидно, я не могу публиковать полезные изображения, поэтому я попытаюсь сделать это с текстом ...

Я только что проверил это, и кажется, что значения полей, которые НЕ являютсяв GROUP BY будут использоваться значения ПЕРВОЙ строки, которая соответствует группе по условию.Это также объясняет воспринимаемую «случайность», с которой сталкиваются другие при выборе столбцов, которые не входят в группу по предложению.

Пример:

Создать таблицу с именем «test» из 2 столбцов с именами «col1» и «col2» с данными, которые выглядят следующим образом:

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

Затем выполните следующий запрос:

выберите col1, col2
из теста
заказ по col2 desc

Вы получитеэтот результат:

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

Теперь рассмотрим следующий запрос:

выберите groupTable.col1, groupTable.col2
из (
выберите col1,col2
из теста
упорядочить по col2 desc
) groupTable
group by groupTable.col1
упорядочить по groupTable.col1 desc

Вы получите такой результат:

3 3
2 3
1 3

Измените подзапрос на asc:

выберите col1, col2
из тестаt
заказ по col2 asc

Результат:

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

Снова используйте это в качестве основы для своего подзапроса:

выберите groupTable.col1, groupTable.col2
из (
выберите col1, col2
из теста
упорядочите по col2 asc
) groupTable
сгруппировать по groupTable.col1
упорядочить по groupTable.col1 desc

Результат:
3 1
2 1
1 2

Теперь вы сможете увидеть, как порядок подзапроса влияет на то, какие значения выбираются для полей, которые выбраны, но не в предложении group by.Это объяснило бы воспринимаемую «случайность», о которой упоминали другие, потому что если подзапрос (или его отсутствие) не объединяется с предложением ORDER BY, то mysql будет захватывать строки по мере их поступления, но путем определения порядка сортировки в подзапросе, который выспособны контролировать это поведение и получать предсказуемые результаты.

0 голосов
/ 27 ноября 2015

Group By выбирает первую запись на основе индекса. Допустим, таблица Log_Analysis_Records_dalhousieShort имеет recoedID в качестве индекса. Следовательно, сгруппируйте по выбранному 11 recordID для IP-адреса 129.173.159.98 среди recordID с 11 по 16. Однако min и max предварительно сгруппированы по операциям таким образом, что значения рассчитываются логически для вас.

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)
0 голосов
/ 14 ноября 2010

Я думал, что первая строка соответствует первичному ключу или любому индексу, потому что похоже, что он работает таким образом, но я пробовал запрос GROUP BY для различных таблиц и не определил ни одного шаблона. *

Поэтому я буду избегать использования любых значений не сгруппированных столбцов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...