Mysql
 sql >> база данни >  >> RDS >> Mysql

Определете ранг въз основа на множество колони в MySQL

В Извлечена таблица (подзаявка вътре в FROM клауза), подреждаме данните си така, че всички редове да имат същия user_id стойностите се събират заедно с допълнително сортиране между тях въз основа на game_detail в низходящ ред.

Сега използваме този набор от резултати и използваме условен CASE..WHEN изрази за оценка на номерирането на редовете. Това ще бъде като техника на Looping (която използваме в кода на приложението, напр.:PHP). Ще съхраняваме стойностите на предишния ред в дефинираните от потребителя променливи и след това ще проверим стойностите на текущия ред спрямо предишния ред. В крайна сметка ще присвоим съответно номер на ред.

Редактиране: Въз основа на MySQL docs и наблюдението на @Gordon Linoff:

Редът на оценка за изрази, включващи потребителски променливи, е недефиниран. Например, няма гаранция, че SELECT @a, @a:[email protected] +1 първо оценява @a и след това изпълнява заданието.

Ще трябва да оценим номера на ред и да зададем user_id стойност до @u променлива в рамките на същия израз.

SET @r :=0, @u :=0; SELECT @r :=CASE WHEN @u =dt.user_id THEN @r + 1 WHEN @u :=dt.user_id /* Забележка :=вместо =*/ 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  

Резултат

<предварителен код>| потребителска_игра_ранг | потребителски_идентификатор | подробности за играта | 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 |

Преглед на DB Fiddle

Интересна бележка от MySQL Документи , който открих наскоро:

Предишните версии на MySQL направиха възможно присвояването на стойност на променливата auser в изрази, различни от SET. Тази функционалност се поддържа в MySQL 8.0 за обратна съвместимост, но подлежи на премахване в бъдеща версия на MySQL.

Освен това, благодарение на колега член на SO, попаднах на този блог от MySQL Team:https://mysqlserverteam.com/row-numbering-ranking-how-to-use-less-user-variables-in-mysql-queries/

Общото наблюдение е, че се използва ORDER BY с оценка на потребителските променливи в същия блок на заявка, не гарантира, че стойностите винаги ще бъдат правилни. Както MySQL оптимизатор може идват на мястото си и променят нашите предполагаеми ред на оценяване.

Най-добрият подход към този проблем би бил да надстроите до MySQL 8+ и да използвате Номер_ред() функционалност:

Схема (MySQL v8.0)

ИЗБЕРЕТЕ user_id, game_id, game_detail, ROW_NUMBER() НАД (ДЯЛА ПО user_id ПОРЪЧАЙТЕ ПО game_detail DESC) КАТО user_game_rank FROM game_logs ORDER BY user_id, user_game_rank; 

Резултат

<предварителен код>| потребителски_идентификатор | game_id | подробности за играта | потребителска_игра_ранг || ------- | ------- | ----------- | -------------- || 6 | 11 | 260 | 1 || 6 | 10 | 100 | 2 || 7 | 10 | 1200 | 1 || 7 | 11 | 500 | 2 || 7 | 12 | 260 | 3 || 7 | 13 | 50 | 4 |

Преглед на 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. Безопасно ли е да съхранявате потребителски имена и пароли в базата данни?

  2. Типове данни на MySQL:Знайте кои да използвате и как

  3. Как да получа текущата часова зона на MySQL?

  4. MySQL InnoDB външен ключ между различни бази данни

  5. Тестване на производителността с помощта на MySQLdump и MySQL Shell Utility