WYBRAĆ LIMIT 1 na wartość kolumny?

11

Powiedzmy, że mam następującą tabelę

-----------------------------
| 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      |
-----------------------------

Jak wybrać jeden wiersz na user_id? Więc moje wyniki to:

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

Czy jest to możliwe dzięki pojedynczemu wydajnemu zapytaniu? Czy konieczne jest dokonanie wyboru podrzędnego? Czy można w jakiś sposób użyć DISTINCTjednej kolumny?

Jake Wilson
źródło

Odpowiedzi:

9

Do tego GROUP BYsłuży. Uzyskaj jeden wiersz (na grupę). W tym przypadku, to pokaże wszystkie różne user_idwartości, a dla pozostałych kolumn, można (trzeba) użyć funkcji agregujących jak MIN(), MAX(), AVG(), SUM()co będzie mieć więcej niż jedną wartość w każdej grupie i tylko jeden może być pokazane.

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 pozwala również na następujące niekonwencjonalne rozwiązanie, które zwróci jeden (mniej lub bardziej losowy) komentarz na użytkownika:

SELECT
    user_id
  , comment
FROM
    tableX
GROUP BY
    user_id ;

To ostatnie zapytanie nie będzie działać, ale zgłosi błąd, jeśli ONLY_FULL_GROUP_BYwłączony jest tryb (bardziej rygorystyczny) . W niedawno wydanej wersji 5.7 ten tryb jest domyślny i dostępna jest nowa funkcja ANY_VALUE(). Aby uzyskać więcej informacji, zobacz stronę MySQL HandlingGROUP BY . Zapytanie można teraz napisać:

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

Zauważ, że w wersji „niekonwencjonalnej” lub przy użyciu ostatniej ANY_VALUE()funkcji, jeśli dodamy więcej kolumn na SELECTliście, nie gwarantuje się, że ich wartości pochodzą z tego samego wiersza, a tylko z wiersza z tej samej grupy. Sposób ich wyboru nie jest dokładnie losowy, zależy od planu wykonania i zastosowanych indeksów.

ypercubeᵀᴹ
źródło
Czy istnieją inne sposoby określenia, który wiersz zostanie pobrany dla identyfikatora użytkownika? W jakikolwiek sposób określić rodzaj ORDER BY?
Jake Wilson,
Poza tym MINi MAX?
ypercubeᵀᴹ
1
To jest bardziej złożone. Zobacz inne pytanie: Zapytanie MySQL - jak uzyskać najnowsze dane demograficzne?
ypercubeᵀᴹ
2
Znajdziesz również mnóstwo podobnych problemów na stronie SO, pod [greatest-n-per-group]tagiem.
ypercubeᵀᴹ
1
@ T.BrianJones masz na myśli w zapytaniu „niekonwencjonalnym”, jeśli dodasz wszystkie inne kolumny z listy WYBIERZ? To pierwszy, mogą nie pochodzić z tego samego rzędu. To nie jest dokładnie losowe, ale wartości mogą pochodzić z różnych wierszy (z tej samej grupy).
ypercubeᵀᴹ