Получите одну строку из целевой таблицы для каждой строки в исходной таблице в соответствии с некоторым порядком

#sql

Вопрос:

У меня есть таблицы source и target определено как:

 CREATE TABLE source (id BIGINT PRIMARY KEY);
CREATE TABLE target (id BIGINT PRIMARY KEY, source_id BIGINT REFERENCES source(id), score INT);
 

Я хотел бы получить запрос, который возвращает значение target с наибольшим score значением для каждого source .

Я легко могу получить это target для конкретного source :

 SELECT * FROM target WHERE source_id = ? ORDER BY score DESC LIMIT 1;
 

Но я хотел бы использовать один запрос, чтобы получить наивысшую оценку target для каждого источника.

Самый простой способ, который я нашел для этого, специфичен для PostgreSQL и использует LATERAL ключевое слово:

 SELECT target.*
FROM 
  source, 
  LATERAL (
    SELECT * FROM target
    WHERE source_id = source.id
    ORDER BY score DESC
    LIMIT 1
  ) AS target;
 

Есть ли простой способ сделать это с помощью стандартного SQL? Возможно, используя CTE или GROUP BY пункт?

Комментарии:

1.Отметьте свой вопрос в базе данных, которую вы используете. LATERAL является стандартным SQL, поэтому ваша конкретная проблема на 100% неясна.

Ответ №1:

Вы можете использовать функцию окна

 select * 
from (
    select *,
       row_number() over(partition by source_id order by score desc) rn
    from Target
) t
where rn = 1;
 

Ответ №2:

Следующий запрос вернет все записи из целевой таблицы с соответствующим максимальным баллом для каждого источника.

     select max(t.score) over (partition by t.source_id) as max_score_per_source, t.* 
    from target t
 

С помощью over() можно указать предложение window, которое работает аналогично функции group by, но не уменьшает количество записей для агрегирования. В вашем случае это лучший подход. Если бы кто-то хотел использовать group by, то также работал бы объединенный дополнительный выбор.

Комментарии:

1. Спасибо за ваш ответ. Я думаю , что это все равно вернет все строки target , но я просто хочу, чтобы каждая строка была отдельной source_id .

2. Да, действительно, я пропустил часть, касающуюся одной строки на идентификатор источника. Извини за это.