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

Как да изберете първия ред във всяка ГРУПА ПО ГРУПА

Проблем:

Групирате данните си с GROUP BY и би искал да показва само първия ред от всяка група.

Пример:

Нашата база данни има таблица с име exam_results с данни в следната таблица:

first_name фамилно_име година резултат
Джон Клайн 2020 40
Едит Черно 2020 43
Отметка Джонсън 2019 32
Лора Лято 2020 35
Кейт Смит 2019 41
Якоб Черно 2019 44
Том Бенет 2020 38
Емили Кели 2020 43

За всяка година нека намерим ученика с най-добрия result . Ако в група има двама ученици, изравнени за най-добрия, ние произволно ще изберем един от тях за показване.

Решение:

WITH added_row_number AS (
  SELECT
    *,
    ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
  FROM exam_results
)
SELECT
  *
FROM added_row_number
WHERE row_number = 1;

Резултатът е:

first_name фамилно_име година резултат номер_ред
Якоб Черно 2019 44 1
Емили Кели 2020 43 1

Дискусия:

Първо, трябва да напишете CTE, в който да присвоите номер на всеки ред във всяка група. За да направите това, можете да използвате ROW_NUMBER() функция. В OVER() , посочвате групите, на които трябва да бъдат разделени редовете (PARTITION BY ) и реда, в който числата трябва да бъдат присвоени на редовете (ORDER BY ).

Разгледайте резултата от вътрешната заявка:

SELECT
  *,
  ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
FROM exam_results;
first_name фамилно_име година резултат номер_ред
Якоб Черно 2019 44 1
Кейт Смит 2019 41 2
Отметка Джонсън 2019 32 3
Емили Кели 2020 43 1
Едит Черно 2020 43 2
Джон Клайн 2020 40 3
Том Бенет 2020 38 4
Лора Лято 2020 35 5

Вие задавате номерата на редовете във всяка група (т.е. година). Всеки ред има номер на ред въз основа на стойността на result колона. Редовете са сортирани в низходящ ред поради DESC ключова дума след ORDER BY result . Дори ако има няколко реда в рамките на група, които имат една и съща стойност на result , редовете все още получават различни номера. Тук Едит Блек и Емили Кели имат същия result но различни номера на редовете. За да промените това поведение и да зададете същия номер на ред за същия резултат в рамките на група, използвайте RANK() или DENSE_RANK() вместо ROW_NUMBER() .

Във външната заявка избирате всички данни от CTE (added_row_number ) и използвайте WHERE условие, за да посочите кой ред да се показва от всяка група. Тук искаме да покажем първия ред, така че условието е row_number = 1 .

Имайте предвид, че можете лесно да промените решението, за да получите например втория ред от всяка група.

WITH added_row_number AS (
  SELECT
    *,
    ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
  FROM exam_results
)
SELECT
  *
FROM added_row_number
WHERE row_number = 2;

Ето резултата:

first_name фамилно_име година резултат номер_ред
Кейт Смит 2019 41 2
Едит Черно 2020 43 2

От друга страна, ако искате да получите редовете с втората най-висока стойност на result във всяка група трябва да използвате DENSE_RANK() функция. Докато ROW_NUMBER() функцията създава последователни числа за всеки ред в група, което води до различни стойности, присвоени на редовете със същия резултат, DENSE_RANK() функция дава едно и също число на редовете със същия резултат.

WITH added_dense_rank AS (
  SELECT
    *,
    DENSE_RANK() OVER(PARTITION BY year ORDER BY result DESC) AS rank
  FROM exam_results
)
SELECT
  *
FROM added_dense_rank
WHERE rank = 2;
first_name фамилно_име година резултат ранг
Кейт Смит 2019 41 2
Джон Клайн 2020 40 2

Можете да видите, че Джон Клайн има втората най-висока стойност на result (40) за 2020 г. Джон Клайн всъщност е третото лице в групата, но първите двама ученици имат същия result и двете имат rank = 1 .


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Свързване с Teradata в IRI Workbench

  2. Съхранение на файлове в SQL база данни с помощта на FILESTREAM – част 1

  3. Как да разрешим грешката `prisma/client все още не е инициализиран` ​​на Vercel

  4. Профилиране на данни:Откриване на подробности за данните

  5. Защо множеството JOIN са лоши за заявка или не пречат на оптимизатора