我知道我需要使用子查询,但我不确定如何去做。我每列ID有多个条目,但我想将它们显示为单行。这是表设计:
UUID | position_id | spot
-----+-------------+-----
111 | 1 | left
112 | 1 | right
113 | 3 | center
114 | 4 | right
我想输出这些数据的方式如下:
postion_1_left | position_1_right | postion_3_center | position_4_right
---------------+------------------+------------------+-----------------
true | true | true | true
这样做的原因是我想将这些数据放入BIRT报告中,并且将每个position_id和spot的绝对值设置为true或false会使报告更好。报告看起来如此:
left | center | right
-----------+-------+--------+-----------
position 1 | yes | no | yes
position 2 | no | no | no
position 3 | no | yes | no
position 4 | no | no | yes
我想不出更好的方法,所以如果有人有建议我会接受它。否则我将继续这个布局,但我很难想出查询。我尝试从这样的查询开始:
SELECT (SELECT spot FROM positions_table WHERE position_id = 3 AND spot = 'left')
from positions_table
WHERE uuid = 'afb36733'
但显然这不起作用。
答案 0 :(得分:2)
由于您只是希望检查某个有限列表中是否有spot
- ('left', 'center', 'right')
- 对于每个position_id
,我会看到一个非常简单的解决方案,使用{ {3}}(参见bool_or
aggregation function):
SELECT
pt.position_id,
bool_or(pt.spot = 'left') AS left,
bool_or(pt.spot = 'right') AS right,
bool_or(pt.spot = 'center') AS center
FROM
positions_table pt
GROUP BY
pt.position_id
ORDER BY
pt.position_id;
结果:
position_id | left | right | center
-------------+------+-------+--------
1 | t | t | f
3 | f | f | t
4 | f | t | f
(3 rows)
然后,您可以使用CASE
展开它以更好地格式化(或在表示层中执行此操作):
SELECT
pt.position_id,
CASE WHEN bool_or(pt.spot = 'left') THEN 'yes' ELSE 'no' END AS left,
CASE WHEN bool_or(pt.spot = 'right') THEN 'yes' ELSE 'no' END AS right,
CASE WHEN bool_or(pt.spot = 'center') THEN 'yes' ELSE 'no' END AS center
FROM
positions_table pt
GROUP BY
pt.position_id
ORDER BY
pt.position_id;
结果:
position_id | left | right | center
-------------+------+-------+--------
1 | yes | yes | no
3 | no | no | yes
4 | no | yes | no
(3 rows)
旋转的另一个常见选择是:
但由于它只是真/假,bool_or
似乎绰绰有余。
答案 1 :(得分:1)
使用generate_series()
填补position_ids
中的空白,并将spots
汇总到id
的数组:
select
id,
coalesce('left' = any(arr), false) as left,
coalesce('center' = any(arr), false) as center,
coalesce('right' = any(arr), false) as right
from (
select id, array_agg(spot) arr
from generate_series(1, 4) id
left join positions_table on id = position_id
group by 1
) s
order by 1;
id | left | center | right
----+------+--------+-------
1 | t | f | t
2 | f | f | f
3 | f | t | f
4 | f | f | t
(4 rows)