postgresql выберите запрос - PullRequest
       3

postgresql выберите запрос

2 голосов
/ 29 января 2012
create temp table tmp_apps (
  id integer
);

create temp table tmp_pos (
     tmp_apps_id integer,
     position integer
);

insert into tmp_apps
select 1 id union
select 2 id 
;

insert into tmp_pos (tmp_apps_id, position)
select 1 tmp_apps_id, 1 as position union all
select 1 tmp_apps_id, 1 as position union all
select 1 tmp_apps_id, 2 as position union all
select 1 tmp_apps_id, 3 as position union all
select 1 tmp_apps_id, 3 as position union all
select 2 tmp_apps_id, 1 as position
;
/*
Expected result:
tmp_apps_id tmp_pos_position
1           1,2
2           1
*/

Как получить первые две запятые, отдельные tmp_pos.position для каждого tmp_apps.id
Возможно?

Ответы [ 3 ]

1 голос
/ 29 января 2012
select tmp_apps_id, string_agg(position::text,',')
from (
 select tmp_apps_id, position,
        row_number() over (partition by tmp_apps_id order by position)
 from (
  select distinct tmp_apps_id, tmp_pos.position from tmp_pos
 ) x
) x
where row_number <= 2
group by tmp_apps_id;
1 голос
/ 29 января 2012
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 предлагают одинаково хорошие решения.В таком случае вы можете использовать тонкую разницу, если вы знаете это.Я ожидаю, что это будет немного быстрее.

0 голосов
/ 29 января 2012

Попробуйте, используя array_agg или string_agg, в зависимости от вашей версии Postgres:

SELECT tmp_apps_id, array_agg(tmp_pos_position)
FROM tmp_pos_position
GROUP BY tmp_apps_id

В 9.0 используйте функцию string_agg:

SELECT tmp_apps_id, string_agg(tmp_pos_position, ',')
FROM tmp_pos_position
GROUP BY tmp_apps_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...