postgresql选择查询

时间:2012-01-28 21:27:19

标签: sql postgresql

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获得前2个逗号分隔,不同的tmp_apps.id 有可能吗?

3 个答案:

答案 0 :(得分:1)

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 :(得分:1)

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 来获取不同的值,您可以应用window function row_number()(解决方案的关键元素)相同的查询级别,不需要另一个子查询(或CTE)。

原因是聚合(GROUP BY)在窗口功能之前应用,而{/ 1}}应用之后。在许多情况下,DISTINCTDISTINCT都提供同样出色的解决方案。在这样的情况下,如果你知道的话,你可以将微妙的差异用于良好的用途。我希望这会快得多。

答案 2 :(得分:0)

使用array_aggstring_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