Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Określ rangę na podstawie wielu kolumn w MySQL

W tabeli pochodnej (podzapytanie wewnątrz FROM klauzuli), uporządkujemy nasze dane tak, aby wszystkie wiersze miały ten sam user_id wartości łączą się, z dalszym sortowaniem między nimi na podstawie game_detail w porządku malejącym.

Teraz używamy tego zestawu wyników i używamy warunkowego CASE..WHEN wyrażenia do oceny numeracji wierszy. Będzie to jak technika Looping (której używamy w kodzie aplikacji, np.:PHP). Przechowalibyśmy wartości poprzedniego wiersza w Zmiennych zdefiniowanych przez użytkownika, a następnie porównalibyśmy wartości bieżącego wiersza z wartościami poprzedniego wiersza. Ostatecznie odpowiednio przypiszemy numer wiersza.

Edytuj: Na podstawie dokumentacji MySQL i obserwacja @Gordon Linoff:

Kolejność oceny wyrażeń zawierających zmienne użytkownika jest niezdefiniowana. Na przykład nie ma gwarancji, że SELECT @a, @a:[email protected] +1najpierw ocenia @a, a następnie wykonuje zadanie.

Będziemy musieli ocenić numer wiersza i przypisać user_id wartość do @u zmienna w ramach tego samego wyrażenia.

SET @r := 0, @u := 0; 
SELECT
  @r := CASE WHEN @u = dt.user_id 
                  THEN @r + 1
             WHEN @u := dt.user_id /* Notice := instead of = */
                  THEN 1 
        END AS user_game_rank, 
  dt.user_id, 
  dt.game_detail, 
  dt.game_id 

FROM 
( SELECT user_id, game_id, game_detail
  FROM game_logs 
  ORDER BY user_id, game_detail DESC 
) AS dt 

Wynik

| user_game_rank | user_id | game_detail | game_id |
| -------------- | ------- | ----------- | ------- |
| 1              | 6       | 260         | 11      |
| 2              | 6       | 100         | 10      |
| 1              | 7       | 1200        | 10      |
| 2              | 7       | 500         | 11      |
| 3              | 7       | 260         | 12      |
| 4              | 7       | 50          | 13      |

Wyświetl na DB Fiddle

Ciekawa notatka z Dokumentów MySQL , który niedawno odkryłem:

Poprzednie wydania MySQL umożliwiały przypisanie wartości do zmiennej auser w instrukcjach innych niż SET. Ta funkcja jest obsługiwana w MySQL 8.0 w celu zapewnienia kompatybilności wstecznej, ale może zostać usunięta w przyszłej wersji MySQL.

Ponadto, dzięki członkowi SO, natknąłem się na ten blog zespołu MySQL:https://mysqlserverteam.com/row-numbering-ranking-how-to-use-less-user-variables-in-mysql-queries/

Ogólna obserwacja jest taka, że ​​używając ORDER BY z oceną zmiennych użytkownika w tym samym bloku zapytania, nie gwarantuje, że wartości będą zawsze poprawne. Optymalizator MySQL może wejść na miejsce i zmienić nasze domniemane kolejność oceny.

Najlepszym podejściem do tego problemu byłoby uaktualnienie do MySQL 8+ i wykorzystanie Row_Number() funkcjonalność:

Schemat (MySQL v8.0)

SELECT user_id, 
       game_id, 
       game_detail, 
       ROW_NUMBER() OVER (PARTITION BY user_id 
                          ORDER BY game_detail DESC) AS user_game_rank 
FROM game_logs 
ORDER BY user_id, user_game_rank;

Wynik

| user_id | game_id | game_detail | user_game_rank |
| ------- | ------- | ----------- | -------------- |
| 6       | 11      | 260         | 1              |
| 6       | 10      | 100         | 2              |
| 7       | 10      | 1200        | 1              |
| 7       | 11      | 500         | 2              |
| 7       | 12      | 260         | 3              |
| 7       | 13      | 50          | 4              |

Wyświetl na DB Fiddle



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dołącz do tabel z problemem SUM w MYSQL

  2. Jak zapisać podpis w MySQL

  3. Porównanie wyszukiwarek pełnotekstowych - Lucene, Sphinx, Postgresql, MySQL?

  4. Jak sprawdzić, kiedy serwer MySQL/MariaDB został uruchomiony?

  5. Jaki jest odpowiednik LEN() w MySQL?