ГРУППА ПО x против DISTINCT(x)

#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, если вы запрашиваете индексированное поле и имеете ОГРАНИЧЕНИЕ, потому что оно будет использовать индекс, а не временную таблицу

Смотрите эти ссылки:


Пример:

 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