ВИБРАТИ ЛІМІТ 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(). Докладніші відомості див. У розділі ОбробкаGROUP BY сторінки MySQL . Запит можна написати зараз:

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

Зауважте, що або з "неортодоксальною" версією, або з використанням недавньої ANY_VALUE()функції, якщо ми додамо більше стовпців у SELECTсписку, їхні значення не гарантуються з того самого рядка, просто з рядка в тій же групі. Спосіб їх вибору не є абсолютно випадковим, залежить від плану виконання та використовуваних індексів.


Чи є інші способи вказати, який рядок буде виведено для user_id? Будь-який спосіб вказати ЗАМОВЛЕННЯ за родом?
Джейк Вілсон

Крім того 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.