#mysql #group-by #distinct
#mysql #группировка по #distinct
Вопрос:
Если у меня есть таблица с повторяющимися идентификаторами, я получу тот же результат, если я использую GROUP BY id
, как если бы я использовал SELECT DISTINCT(id)
, верно?
Итак, когда я должен предпочесть один вариант другому?
Комментарии:
1. Нет необходимости заключать столбцы и / или выражения в скобки;
DISTINCT
ключевое слово применяется ко всему списку ВЫБОРА. Скобки вокругid
не влияют на результаты запроса или план выполнения.2.
group by
является более общим.distinct
на самом деле это просто сокращение. Единственный раз, когда это действительно необходимо, — это когда вы это делаетеselect distinct *
, потомуgroup by *
что это запрещено. Другими словами, сначала сосредоточьтесь на изучении и использованииgroup by
.3. … хотя
DISTINCT *
, казалось бы, бессмысленно. @doub1ejack как правило, в отсутствие каких-либо агрегирующих функций GROUP BY не следует использовать в качестве замены DISTINCT . При определенных обстоятельствах это может привести к вводящим в заблуждение результатам.
Ответ №1:
Вы должны использовать GROUP BY
, если вам нужны агрегированные функции, например SUM
, и т.д. MAX
Если вам нужна только группировка столбцов, они одинаковы (и используют один и тот же план).
Пожалуйста, обратите внимание, что DISTINCT
это не функция, поэтому это предложение:
SELECT DISTINCT(id), othercol
который такой же (за исключением порядка столбцов), как
SELECT DISTINCT othercol, (id)
или просто
SELECT DISTINCT othercol, id
может по-прежнему выдавать дубликаты id
, если есть записи с одинаковыми id
, но разными othercol
.
Комментарии:
1. «все равно может выдавать дубликаты идентификатора, если есть записи с одинаковым идентификатором, но другим другим кодом» 1.
DISTINCT
означает, что сама строка уникальна, что означает комбинацию всех возвращаемых столбцов.2. Итак, моя предпосылка, что GROUP BY и DISTINCT возвращают один и тот же результат, не совсем точна? Если я вас правильно понимаю, DISTINCT возвращает уникальные строки, но GROUP BY возвращает строки ~ свернутые определенным полем. .. хотя это часто будет выглядеть одинаково при сравнении простых запросов. Приятно знать — спасибо.
Ответ №2:
DISTINCT и GROUP BY обычно генерируют один и тот же план запроса, поэтому производительность должна быть одинаковой для обеих конструкций запроса. GROUP BY следует использовать для применения агрегированных операторов к каждой группе. Если все, что вам нужно, это удалить дубликаты, тогда используйте DISTINCT. Если вы используете план выполнения подзапросов для этого запроса, то в этом случае вам нужно проверить план выполнения, прежде чем принимать решение о том, какой из них быстрее.
Example of DISTINCT:
SELECT DISTINCT Employee, Rank
FROM Employees
Example of GROUP BY:
SELECT Employee, Rank
FROM Employees
GROUP BY Employee, Rank
Example of GROUP BY with aggregate function:
SELECT Employee, Rank, COUNT(*) EmployeeCount
FROM Employees
GROUP BY Employee, Rank
Ссылка: Пинал Дейв (http://blog .SQLAuthority.com )
Ответ №3:
Просто дополнительная информация:
Лучше использовать GROUP BY вместо DISTINCT, если вы запрашиваете индексированное поле и имеете ОГРАНИЧЕНИЕ, потому что оно будет использовать индекс, а не временную таблицу
Смотрите эти ссылки:
- http://dev.mysql.com/doc/refman/5.7/en/group-by-optimization.html
- http://dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html
«Если есть предложение ORDER BY и другое предложение GROUP BY, или если ORDER BY или GROUP BY содержит столбцы из таблиц, отличных от первой таблицы в очереди объединения, создается временная таблица»
Пример:
MariaDB [my_db]> EXPLAIN SELECT DISTINCT p.data_prefix FROM my_table p;
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ --------------------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ --------------------------
| 1 | SIMPLE | p | range | NULL | data_prefix | 33 | NULL | 18 | Using index for group-by |
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ --------------------------
1 row in set (0.00 sec)
MariaDB [my_db]> EXPLAIN SELECT DISTINCT p.data_prefix FROM my_table p limit 0,40;
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ -------------------------------------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ -------------------------------------------
| 1 | SIMPLE | p | range | NULL | data_prefix | 33 | NULL | 18 | Using index for group-by; Using temporary |
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ -------------------------------------------
1 row in set (0.00 sec)
MariaDB [my_db]> EXPLAIN SELECT p.data_prefix FROM my_table p group by p.data_prefix;
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ --------------------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ --------------------------
| 1 | SIMPLE | p | range | NULL | data_prefix | 33 | NULL | 18 | Using index for group-by |
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ --------------------------
1 row in set (0.00 sec)
MariaDB [my_db]> EXPLAIN SELECT p.data_prefix FROM my_table p group by p.data_prefix limit 0,40;
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ --------------------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ --------------------------
| 1 | SIMPLE | p | range | NULL | data_prefix | 33 | NULL | 18 | Using index for group-by |
------ ------------- ------- ------- --------------- ------------ --------- ------ ------ --------------------------
1 row in set (0.00 sec)
MariaDB [my_db]>
Ответ №4:
Пример того, когда вы можете предпочесть group by
a distinct
. Рассмотрим сценарий, в котором window function
(не обязательно row_number()) необходимо применить к отдельному результирующему набору. Соблюдая порядок операций, вам придется использовать что-то подобное, используя distinct
select id, row_number() over (order by id) as rn
from (select distinct id from my_table) t;
То же самое может быть достигнуто без использования подзапроса с использованием group by
select id, row_number() over (order by id) as rn
from my_table
group by id;
Это было возможно, потому window functions
что применяются после group by
, но до distinct