SELECT LIMIT 1 для каждого значения столбца?


11

Допустим, у меня есть следующая таблица

-----------------------------
| user_id   | comment       |
-----------------------------
| 2         | thats cool    |
| 2         | awesome       |
| 3         | i hate this   |
| 3         | okay          |
| 6         | this is weird |
| 6         | hello?        |
| 6         | what is it    |
| 9         | how are you   |
| 16        | too slow      |
| 16        | yes           |
| 17        | alrighty      |
-----------------------------

Как вы можете выбрать один ряд на user_id? Так что мои результаты будут:

-----------------------------
| user_id   | comment       |
-----------------------------
| 2         | thats cool    |
| 3         | i hate this   |
| 6         | this is weird |
| 9         | how are you   |
| 16        | too slow      |
| 17        | alrighty      |
-----------------------------

Возможно ли это с помощью одного эффективного запроса? Или подвыбор необходим? Можно ли как-то использовать DISTINCTодин столбец?

Ответы:


9

Это то, что GROUP BYиспользуется для. Получите один ряд (на группу). В этом случае он будет показывать все различные user_idзначения и для остальных столбцов, вы можете (должны) использовать агрегатные функции , такие как MIN(), MAX(), AVG(), SUM()как вы будете иметь более одного значения для каждой группы и может быть показан только один.

SELECT
    user_id
  , MIN(comment) AS comment  -- it will show the first in alphabetical order  
                             -- you could also use MAX()
FROM
    tableX
GROUP BY
    user_id ;

MySQL также допускает следующее неортодоксальное решение, которое будет возвращать один (более или менее случайный) комментарий на пользователя:

SELECT
    user_id
  , comment
FROM
    tableX
GROUP BY
    user_id ;

Этот последний запрос не будет работать, но вызовет ошибку, если ONLY_FULL_GROUP_BYвключен (более строгий) режим. В недавно выпущенной версии 5.7 этот режим используется по умолчанию и предоставляется новая функция ANY_VALUE(). Для получения более подробной информации см. Раздел «Обработка MySQL»GROUP BY . Запрос можно написать сейчас:

SELECT
    user_id
  , ANY_VALUE(comment) AS comment
FROM
    tableX
GROUP BY
    user_id ;

Обратите внимание, что при использовании «неортодоксальной» версии или использовании недавней ANY_VALUE()функции, если мы добавим больше столбцов в SELECTсписок, их значения не обязательно будут из одной строки, только из строки в той же группе. Способ их выбора не является абсолютно случайным, зависит от плана выполнения и используемых индексов.


Есть ли другие способы указать, какая строка будет извлечена для user_id? Любой способ указать вид ORDER BY?
Джейк Уилсон

Кроме того, MINа MAX?
ypercubeᵀᴹ

1
Тогда это сложнее. Посмотрите этот другой вопрос: MySQL Query - Как получить самые последние демографические данные?
ypercubeᵀᴹ

2
Вы также найдете массу подобных проблем на SO сайте под [greatest-n-per-group]тегом.
ypercubeᵀᴹ

1
@ T.BrianJones Вы имеете в виду в «неортодоксальном» запросе, добавляете ли вы все остальные столбцы в список SELECT? Это первое, они могут быть не из одного ряда. Это не совсем случайно, но значения могут быть из разных строк (из одной группы).
ypercubeᵀᴹ
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.