Использование ключевого слова DISTINCT для удаления дубликатов

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

Решение
Используйте ключевое слово DISTINCT для выбора уникальных значений и конструкцию COUNT(DISTINCT) – для подсчета их количества.

Обсуждение
Удаление дубликатов для получения информации о том, какие значения или строки входят в набор данных, – это суммарная операция, не требующая использования агрегирующей функции. Используем ключевое слово DISTINCT (или его синоним DISTINCTROW). DISTINCT сокращает результат запроса и часто используется в сочетании с ORDER BY для расположения значений в более удобном порядке. Например, если вы хотите узнать имена водителей из таблицы driver_log, выполните такой запрос:

mysql> SELECT DISTINCT name FROM driver_log ORDER BY name;

+-------+
| name |
+-------+
| Ben |
| Henry |
| Suzi |
+-------+

Запрос без использования ключевого слова DISTINCT выводит те же самые имена, но в менее удобной форме:

mysql> SELECT name FROM driver_log;

+-------+
| name |
+-------+
| Ben |
| Suzi |
| Henry |
| Henry |
| Ben |
| Henry |
| Suzi |
| Henry |
| Ben |
| Henry |
+-------+

Если вы хотите узнать, сколько разных водителей включено в таблицу, используйте конструкцию COUNT(DISTINCT):

mysql> SELECT COUNT(DISTINCT name) FROM driver_log;

+------------------------------+
| COUNT(DISTINCT name) |
+------------------------------+
| 3 |
+------------------------------+

Конструкция COUNT(DISTINCT) игнорирует значения NULL.


Если вы хотите сосчитать и значения NULL (если они присутствуют), сделайте следующее:

COUNT(DISTINCT знач) + IF(COUNT(IF(знач IS NULL,1,NULL))=0,0,1)

Того же эффекта можно достичь при помощи таких выражений:

COUNT(DISTINCT знач) + IF(SUM(ISNULL(знач))=0,0,1)
COUNT(DISTINCT знач) + (SUM(ISNULL(знач))!=0)

Конструкция COUNT(DISTINCT) доступна, начиная с MySQL версии 3.23.2. Если вы работаете с более ранней версией, необходимо использовать какой-то обходной маневр для вычисления количества строк запроса SELECT DISTINCT.

Можно, например, выбрать уникальные значения в отдельную таблицу, а затем применить COUNT(*) для подсчета количества строк новой таблицы.

Запросы DISTINCT часто используются в сочетании с агрегирующими функциями для получения более полного описания имеющихся данных. Например, если применить COUNT(*) к таблице customer, вы узнаете количество своих клиентов, применив DISTINCT к значениям таблицы state, вы узнаете,в каких штатах живут ваши клиенты. Если же выполнить COUNT(DISTINCT) к значениям state, то будет выведено количество штатов, в которых есть ваши клиенты.

Если использовать DISTINCT для нескольких столбцов, то будут выведены уникальные комбинации значений этих столбцов, а COUNT(DISTINCT) вычислит количество таких комбинаций.


Следующий запрос находит в таблице mail различные пары отправитель-получатель (srcuser-dstuser) и считает иколичество:

mysql> SELECT DISTINCT srcuser, dstuser FROM mail
-> ORDER BY srcuser, dstuser;

+---------+---------+
| srcuser | dstuser |
+---------+---------+
| barb | barb |
| barb | tricia |
| gene | barb |
| gene | gene |
| gene | tricia |
| phil | barb |
| phil | phil |
| phil | tricia |
| tricia | gene |
| tricia | phil |
+---------+---------+

mysql> SELECT COUNT(DISTINCT srcuser, dstuser) FROM mail;

+------------------------------------------+
| COUNT(DISTINCT srcuser, dstuser) |
+------------------------------------------+
| 10 |
+------------------------------------------+

Можно применять DISTINCT не только к столбцам, но и к выражениям. Чтобы вычислить количество часов дня, в которые отправлялись сообщения таблицы mail, будем учитывать неповторяющиеся значения HOUR():

mysql> SELECT COUNT(DISTINCT HOUR(t)) FROM mail;

+----------------------------------+
| COUNT(DISTINCT HOUR(t)) |
+----------------------------------+
| 12 |
+----------------------------------+

Чтобы узнать, какие именно это были часы, выведем их список:

mysql> SELECT DISTINCT HOUR(t) FROM mail ORDER BY 1;

+----------+
| HOUR(t) |
+----------+
| 7 |
| 8 |
| 9 |
| 10 |
| 11 |
| 12 |
| 13 |
| 14 |
| 15 |
| 17 |
| 22 |
| 23 |
+----------+

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



Оцените статью: (0 голосов)
0 5 0

Статьи из раздела MySQL на эту тему:
Выбор групп только с определенными характеристиками
Группирование по результатам выражения
Итоги и значения NULL
Итоги по датам
Классификация некатегориальных данных

Вернуться в раздел: MySQL / 7. Формирование итогов