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?

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.


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ᵀᴹ
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.