2015-02-20 2 views
-1

Вопрос: почему запрос с GROUP BY HOUR (временной метки) функция в следующем примере возвращает UserCount временную метку @2015-02-18 23:16:25 вместо, например, первое вхождение @2015-02-18 23:14:12?Почему GROUP BY HOUR (временная метка) возвращает определенную временную метку?

Каков механизм внутри MySQL, который определяет этот выбор?


Вот результат группы по часовому запросу:

mysql> SELECT *, COUNT(user_id) AS usercount FROM table_log WHERE user_id = 1 GROUP BY HOUR(timestamp) ORDER BY timestamp,usercount DESC; 

+------+---------+-----------+---------------------+-----------+ 
| id | user_id | user_name | timestamp   | usercount | 
+------+---------+-----------+---------------------+-----------+ 
| 1013 | 1  | 1   | 2015-02-16 00:51:32 |   2 | 
| 1016 | 1  | 1   | 2015-02-16 21:38:52 |   2 | 
| 1018 | 1  | 1   | 2015-02-17 02:05:44 |   3 | 
| 1022 | 1  | 1   | 2015-02-18 04:51:22 |   8 | 
| 1001 | 1  | 1   | 2015-02-18 23:16:25 |  22 | 
| 1005 | 1  | 1   | 2015-02-19 03:06:01 |   5 | 
| 1009 | 1  | 1   | 2015-02-19 05:15:32 |   3 | 
| 1011 | 1  | 1   | 2015-02-19 11:57:26 |   1 | 
| 1012 | 1  | 1   | 2015-02-19 12:09:20 |   1 | 
+------+---------+-----------+---------------------+-----------+ 
9 rows in set (0.01 sec) 

И вот результат регулярного запроса (без группировки):

mysql> SELECT * FROM table_log WHERE user_id = 1 ORDER BY timestamp; 

+------+---------+-----------+---------------------+ 
| id | user_id | user_name | timestamp   | 
+------+---------+-----------+---------------------+ 
| 1013 | 1  | 1   | 2015-02-16 00:51:32 | 
| 1014 | 1  | 1   | 2015-02-16 00:51:38 | 
| 1015 | 1  | 1   | 2015-02-16 03:12:28 | 
| 1016 | 1  | 1   | 2015-02-16 21:38:52 | 
| 1017 | 1  | 1   | 2015-02-16 21:39:33 | 
| 1018 | 1  | 1   | 2015-02-17 02:05:44 | 
| 1019 | 1  | 1   | 2015-02-17 02:05:52 | 
| 1020 | 1  | 1   | 2015-02-17 02:05:55 | 
| 1021 | 1  | 1   | 2015-02-17 05:21:19 | 
| 1022 | 1  | 1   | 2015-02-18 04:51:22 | 
| 1023 | 1  | 1   | 2015-02-18 04:51:31 | 
| 1024 | 1  | 1   | 2015-02-18 04:51:35 | 
| 1025 | 1  | 1   | 2015-02-18 04:51:43 | 
| 1026 | 1  | 1   | 2015-02-18 04:51:46 | 
| 1027 | 1  | 1   | 2015-02-18 04:52:10 | 
| 1028 | 1  | 1   | 2015-02-18 04:52:24 | 
| 1029 | 1  | 1   | 2015-02-18 04:52:31 | 
| 1030 | 1  | 1   | 2015-02-18 23:14:12 | 
| 1031 | 1  | 1   | 2015-02-18 23:14:16 | 
| 1032 | 1  | 1   | 2015-02-18 23:14:53 | 
| 1033 | 1  | 1   | 2015-02-18 23:14:57 | 
| 1034 | 1  | 1   | 2015-02-18 23:14:59 | 
| 1035 | 1  | 1   | 2015-02-18 23:15:02 | 
| 1036 | 1  | 1   | 2015-02-18 23:15:05 | 
| 1037 | 1  | 1   | 2015-02-18 23:15:08 | 
| 1038 | 1  | 1   | 2015-02-18 23:15:10 | 
| 1039 | 1  | 1   | 2015-02-18 23:15:12 | 
| 1040 | 1  | 1   | 2015-02-18 23:15:13 | 
| 1041 | 1  | 1   | 2015-02-18 23:15:14 | 
| 1042 | 1  | 1   | 2015-02-18 23:15:24 | 
| 1043 | 1  | 1   | 2015-02-18 23:15:29 | 
| 1044 | 1  | 1   | 2015-02-18 23:15:39 | 
| 1045 | 1  | 1   | 2015-02-18 23:15:44 | 
| 1046 | 1  | 1   | 2015-02-18 23:16:15 | 
| 1047 | 1  | 1   | 2015-02-18 23:16:20 | 
| 1001 | 1  | 1   | 2015-02-18 23:16:25 | 
| 1002 | 1  | 1   | 2015-02-18 23:35:31 | 
| 1003 | 1  | 1   | 2015-02-18 23:47:20 | 
| 1004 | 1  | 1   | 2015-02-18 23:47:27 | 
| 1005 | 1  | 1   | 2015-02-19 03:06:01 | 
| 1006 | 1  | 1   | 2015-02-19 03:06:05 | 
| 1007 | 1  | 1   | 2015-02-19 03:06:11 | 
| 1008 | 1  | 1   | 2015-02-19 03:06:19 | 
| 1009 | 1  | 1   | 2015-02-19 05:15:32 | 
| 1010 | 1  | 1   | 2015-02-19 05:15:35 | 
| 1011 | 1  | 1   | 2015-02-19 11:57:26 | 
| 1012 | 1  | 1   | 2015-02-19 12:09:20 | 
+------+---------+-----------+---------------------+ 
47 rows in set (0.01 sec) 

ПРИМЕЧАНИЕ: Идентификатор столбец AUTO INC + индекс

+0

Это уникальный столбец идентификатора (самый низкий индекс)? – dev101

+0

Потому что у вас есть несколько значений в группе, и он вытаскивает случайный случай в качестве представителя для группы. Стандартный SQL даже не позволяет вам это делать. Вы должны указать MIN (временная метка), если хотите получить самую раннюю из них. – shawnt00

+0

Также обратите внимание, что HOUR() вернет значение от 0 до 23. Поэтому, когда ваши данные будут распределены в течение нескольких дней, все равно все они попадут в один из 24 разных ведер. – shawnt00

ответ

0

Для полноты Q/A я повторю здесь то, что я уже заметил в разделе комментариев: столбец id (AUTO INC) уникален (индекс) и, по-видимому, также учитывается при выборе значение репрезентативной метки времени. По-видимому, наименьшее значение идентификатора первого столбца, разбросанное в разные дни, но в то же время, всегда «выигрывает» как выбранное значение временной метки в группе.

+0

«AUTO_INCREMENT» на самом деле не является фактором ... кроме того, что MySQL требует, чтобы столбец с AUTO_INCREMENT должен был быть ** индексом **. Наблюдаемое поведение обусловлено ** порядком **, в котором MySQL извлекает строки ... в этом конкретном случае MySQL использует определенный индекс, вероятно, таблица InnoDB, а столбец auto_increment - PRIMARY KEY. Для полноты ответа мы должны действительно указать, что выводы/выводы, сделанные из этого частного случая, не * справедливы для более общего случая. – spencer7593

1

Неопределенный который ряд будет retur Нед. MySQL может возвращать значения из любых строк в группе.

Другие базы данных выдадут исключение с таким запросом. Но MySQL расширяет функциональность и допускает неагрегаты в списке SELECT.

Поведение документировано здесь: http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html

MySQL расширяет использование GROUP BY так, чтобы выбрать список может относиться к неагломерированным столбцам не указанным в пункте GROUP BY. Это означает, что предыдущий запрос является законным в MySQL. Вы можете использовать эту функцию для повышения производительности, избегая ненужной сортировки и группировки столбцов. Однако это полезно, прежде всего, когда все значения в каждом неагрегированном столбце, не названном в GROUP BY, одинаковы для каждой группы. Сервер может выбирать любое значение из каждой группы, поэтому, если они не совпадают, выбранные значения являются неопределенными. Кроме того, на выбор значений из каждой группы не может влиять добавление предложения ORDER BY. Сортировка набора результатов происходит после того, как были выбраны значения, а ORDER BY не влияет на значения в каждой группе, которую выбирает сервер.

+0

Привет, spencer7593, я отвечу на ваш ответ, но я также проанализировал данные (в гораздо большем масштабе), и кажется, что идентификатор столбца (AUTO INC) взят в account - наименьшее значение индекса всегда используется как представитель. Благодаря! – dev101

+0

@ dev101: Это может быть поведение, которое вы наблюдаете, но это поведение * не * гарантировано.И я не думаю, что это свойство AUTO_INCREMENT влияет на поведение, скорее, это * порядок *, в котором MySQL извлекает строки ... и это действительно зависит от того, какой * индекс * используется ... в случае в качестве ключа кластера используется таблица InnoDB, PRIMARY KEY или UNIQUE INDEX. Вероятно, столбец AUTO_INCREMENT является ПЕРВИЧНЫМ КЛЮЧОМ. Если бы MySQL использовал другой индекс для доступа к строкам, вполне вероятно, что «первая» строка из индекса (для группы) была бы единственной. Но опять же ... – spencer7593

+0

@ dev101: ... это поведение * не * гарантировано. Если вам нужна определенная строка, используйте агрегированное выражение ... для получения наименьшего значения, например. используйте 'MIN()'. Если 'sql_mode' включает' ONLY_FULL_GROUP_BY', то MySQL будет вести себя как другие базы данных и отклонять запросы с неагрегатами в списке выбора, которые также не отображаются в предложении GROUP BY. – spencer7593

Смежные вопросы