2016-08-27 8 views
3

Я знаю, что мне нужно использовать подзапросы для этого, но я не уверен, как это сделать. У меня есть несколько записей для идентификатора столбца, но я хочу показать их как одну строку. Вот конструкция стола:Postgres Несколько строк как одиночная строка

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 и точки как истинные или ложные сделают отчет намного приятнее. В докладе будет выглядеть так:

   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

Попытайтесь начать с 'select pos.id, bool_or (spot = 'left'), как осталось от generate_series (1,4), так как pos (id) left присоединяется к вашей_группе по (pos.id = position_id) группой pos. id' – Abelisto

ответ

2

Как вы просто хотите проверить, если у Вас есть данный spot из конечного списка - ('left', 'center', 'right') - для каждого position_id, Я вижу очень простое решение для вашего случая, используя bool_or aggregation function (см also on SQL Fiddle):

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 кажется более чем достаточно здесь.

+0

Это именно то, что я искал! благодаря – Chris

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) 
+0

Это отличное решение. Но я пошел с другим ответом с заявлениями CASE. Спасибо за ответ. – Chris

 Смежные вопросы

  • Нет связанных вопросов^_^