Сравнение строк одной таблицы с несколькими условиями - PullRequest
0 голосов
/ 04 ноября 2018

Вот таблица

ID | Player | Position | Points
1  | Ryan   | QB       | 75
2  | Matt   | RB       | 80
3  | Mike   | WR       | 66
4  | Jay    | QB       | 71
6  | Alvin  | TE       | 73
7  | Adrian | TE       | 84
8  | Hill   | WR       | 71
9  | Charles| RB       | 53
10 | Bell   | WR       | 87
11 | Rob    | TE       | 49
12 | Alex   | RB       | 92
13 | Drew   | QB       | 84
14 | Mack   | TE       | 59
15 | Nick   | WR       | 33

Я хочу сообщить обо всех игроках в положении игрока, имеющего наивысшие очки, и двух лучших игроков других позиций. В этом примере «Алекс» имеет наивысшие баллы и является «РБ». Поэтому я хочу сообщить обо всех игроках из "RB" и топ-2 из "QB", "TE", "WR" и упорядочить по очкам в каждой группе. Я использую sqlite3. Я могу сделать это программно, используя python и sqlite3, но мне было интересно, если это можно сделать только с использованием sql

ID | Player | Position | Points
12 | Alex   | RB       | 92
2  | Matt   | RB       | 80
9  | Charles| RB       | 53
13 | Drew   | QB       | 84
1  | Ryan   | QB       | 75
10 | Bell   | WR       | 87
8  | Hill   | WR       | 71
7  | Adrian | TE       | 84
6  | Alvin  | TE       | 73

Спасибо за вашу помощь

1 Ответ

0 голосов
/ 04 ноября 2018

Это сложно в «традиционном» SQLite. Я бы порекомендовал union all:

with top1 as (
      select t.*
      from t
      order by points desc
      limit 1
     )
select t.*
from t
where t.position = (select t1.position from top1 t1)
union all
select t.*
from t
where t.position <> (select t1.position from top1 t1) and
      (select count(*)
       from t t2
       where t2.position = t.position and
             t2.points >= t.points
      ) <= 2;

Предполагается, что значения points являются уникальными. Связи гораздо сложнее в SQLite.

Я мог бы порекомендовать вам перейти на SQLite версии 3.25.0 или использовать другую базу данных. Такой запрос будет намного проще, если использовать стандартные оконные функции ISO / ANSI.

С оконными функциями это будет выглядеть так:

select t.*
from (select t.*,
             row_number() over (partition by position order by points desc) as seqnum,
             first_value(position) over (order by points desc) as first_position
      from t
     ) t
where seqnum <= 2 or position = first_position
...