WITH x AS (
SELECT tmp_apps_id
, position
, row_number() OVER (PARTITION BY tmp_apps_id ORDER BY position) AS rn
FROM tmp_pos
GROUP BY 1, 2
ORDER BY 1, 2
)
SELECT tmp_apps_id, string_agg(position::text, ', ')
FROM x
WHERE rn < 3
GROUP BY 1;
Это похоже на решение, которое @araqnid разместил немного быстрее меня.
CTE или подзапрос, в этом случае это всего лишь два способа сделать то же самое.
Моя версия отличается в одном важном аспекте:
Используя GROUP BY
вместо DISTINCT
для получения различных значений, вы можете применить оконная функция row_number()
(ключевой элемент для решения) на том же уровне запроса и не требует другого подзапроса (или CTE).
Причина этого в том, что агрегация(GROUP BY
) применяется до оконных функций, в то время как DISTINCT
применяется после .Во многих ситуациях DISTINCT
и GROUP BY
предлагают одинаково хорошие решения.В таком случае вы можете использовать тонкую разницу, если вы знаете это.Я ожидаю, что это будет немного быстрее.