2016-03-03 2 views
2

Я использую Apache Derby 10.10.Запрос для ранжирования строк в группах

У меня есть список участников и хотели бы, чтобы вычислить их ранг в своей стране, как это:

|  Country |   Participant | Points | country_rank | 
|----------------|---------------------|--------|--------------| 
|  Australia |  Bridget Ciriac |  1 |   1 | 
|  Australia |  Austin Bjorklun |  4 |   2 | 
|  Australia |  Carrol Motto |  7 |   3 | 
|  Australia |  Valeria Seligma |  8 |   4 | 
|  Australia |  Desmond Miyamot |  27 |   5 | 
|  Australia |  Maryjane Digma |  33 |   6 | 
|  Australia |  Kena Elmendor |  38 |   7 | 
|  Australia |   Emmie Hicke |  39 |   8 | 
|  Australia |  Kaitlyn Mund |  50 |   9 | 
|  Australia | Alisia Vitaglian |  65 |   10 | 
|  Australia |   Anika Bulo |  65 |   11 | 
|    UK |   Angle Ifil |  2 |   1 | 
|    UK |  Demetrius Buelo |  12 |   2 | 
|    UK |  Ermelinda Mell |  12 |   3 | 
|    UK |   Adeline Pee |  21 |   4 | 
|    UK |  Alvera Cangelos |  23 |   5 | 
|    UK | Keshia Mccalliste |  23 |   6 | 
|    UK |  Alayna Rashi |  24 |   7 | 
|    UK | Malinda Mcfarlan |  25 |   8 | 
| United States |  Gricelda Quirog |  3 |   1 | 
| United States |  Carmina Britto |  5 |   2 | 
| United States |   Noemi Blase |  6 |   3 | 
| United States |  Britta Swayn |  8 |   4 | 
| United States |  An Heidelber |  12 |   5 | 
| United States |  Maris Padill |  21 |   6 | 
| United States |  Rachele Italian |  21 |   7 | 
| United States | Jacquiline Speake |  28 |   8 | 
| United States |  Hipolito Elami |  45 |   9 | 
| United States |   Earl Sayle |  65 |   10 | 
| United States |  Georgeann Ves |  66 |   11 | 
| United States |  Conchit Salli |  77 |   12 | 

Схема выглядит следующим образом (sqlfiddle):

create table Country(
    id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, 
    name varchar(255), 
    PRIMARY KEY (id) 
); 

create table Team(
    id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, 
    country_id int not null, 
    PRIMARY KEY (id), 
    FOREIGN KEY (country_id) REFERENCES Country(id) 
); 

create table Participant(
    id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, 
    team_id int not null, 
    name varchar(100), 
    points int, 
    PRIMARY KEY (id), 
    FOREIGN KEY (team_id) REFERENCES Team(id) 
); 

Это то, что Я пробовал:

select 
    Country.name, 
    Participant.name, 
    Participant.points, 
    ROW_NUMBER() OVER(order by Country.name, Participant.points) as country_rank 
from Country 
join Team 
    on Country.id = Team.country_id 
join Participant 
    on Team.id = Participant.team_id; 

Но согласно apache derby doco, оператор OVER() не принимает никаких аргументов.

У кого-нибудь есть способ достичь ранга страны?

ответ

1

Запрос

SELECT c.name AS Country, 
     p.name AS Participant, 
     p.points AS Points, 
     (SELECT COUNT(*) 
     FROM Participant p2 
     JOIN Team t2 ON p2.team_id = t2.id 
     WHERE t2.country_id = t.country_id 
      AND (p2.points < p.points 
       OR p2.points = p.points AND p2.name <= p.name)) AS country_rank 
FROM Country c 
JOIN Team t ON c.id = t.country_id 
JOIN Participant p ON t.id = p.team_id 
ORDER BY c.name, p.points, p.name; 

Объяснение

Простой ANSI-SQL подзапрос может использоваться, чтобы сделать ту же работу, подсчет количества записей для участников в той же стране с более низким счетом или с тем же счетом и именем, которое в алфавитном порядке не выше.

Demo

SQL fiddle demo

+1

Шляпы от вас! Вы лучше справлялись с галстуком! – Parfait

+1

Parfait, я восхищаюсь вашим хорошим спортом – Fidel

0

все, что вам нужно добавить, это раздел по странам, который должен предоставить вам то, что вам нужно.

SELECT 
Country.name, 
Participant.name, 
Participant.points, 
ROW_NUMBER() OVER(PARTITION BY country order by Country.name, Participant.points) as country_rank 
from Country 
join Team 
    on Country.id = Team.country_id 
join Participant 
    on Team.id = Participant.team_id; 
+0

Благодаря виртуальной машины Java, делает PARTITION BY работы в Apache Derby? Я пробовал, но он говорит: «Encountered PARTITION в строке x, столбец y» – Fidel

+0

Я не слишком хорошо знаком с Apache Derby, но я сделал поиск в Google и нашел, что они существуют в apache derby. Вот ссылка https://wiki.apache.org/db-derby/OLAPOperations – JVM

+1

К сожалению, эта страница wiki описала конструкторские предложения для создания такой функциональности, не все из которых фактически закончили создание. –

1

Рассмотрите SQL-запрос, не относящийся к окнам, который использует подзапрос коррелированного агрегатного подсчета. Поскольку столбец группы (Country.name) находится не в той же таблице, что и критерии ранга (Participant.points), нам нужно запустить те же соединения в подзапросе, но переименовать псевдонимы таблицы, чтобы правильно сравнивать внутренние и внешние запросы.

Теперь, конечно же, в идеальном мире, который бы это был, но мы должны теперь учитывать привязанные точки. Поэтому другой очень похожий подзапрос (для тай-брейкера) используется для добавления в первый подзапрос. Этот второй вложенный запрос соответствует внутреннему и внешнему запросам Country.name и Participant.points, но занимает по алфавиту порядка Participant.name.

SELECT 
    Country.name AS Country, 
    Participant.name AS Participant, 
    Participant.points, 
    (SELECT Count(*) + 1 
     FROM Country subC 
     INNER JOIN Team subT 
       ON subC.id = subT.country_id 
     INNER JOIN Participant subP 
       ON subT.id = subP.team_id 
     WHERE subC.name = Country.name 
     AND subP.points < Participant.points) 

    + 

    (SELECT Count(*) 
     FROM Country subC 
     INNER JOIN Team subT 
       ON subC.id = subT.country_id 
     INNER JOIN Participant subP 
       ON subT.id = subP.team_id 
     WHERE subC.name = Country.name 
     AND subP.points = Participant.points 
     AND subP.name < Participant.name) As country_rank 

FROM Country 
INNER JOIN Team 
     ON Country.id = Team.country_id 
INNER JOIN Participant 
     ON Team.id = Participant.team_id 
ORDER BY Country.name, Participant.points; 
Смежные вопросы