2016-02-16 5 views
3

Я пытаюсь построить один-много запросов в PostgreSQL, который смотрит на таблицу клиентов, таблицу транзакций и результат представляет собой таблицу, показывающую, какие продукты приобрел клиент.PostgreSQL от одного до большого числа с кросс-таблицей

table: customers 
id 
1 
2 
3 
4 
5 

table: purchases 
custid product 
1  software 1 
1  software 2 
3  software 2 
3  software 3 
4  software 1 
5  software 1 
5  software 2 
5  software 3 

Результат я хочу, чтобы это:

custid software1 software2 software3 
1  TRUE  TRUE  NULL 
3  NULL  TRUE  TRUE 
4  TRUE  NULL  NULL 
5  TRUE  TRUE  TRUE 

Из того, что я могу сказать, что нужно использовать crosstabpostgreSQL не поддерживает pivot), но я не уверен, что на snytax. Я бы также хорошо, если выход включен ряд:

custid software1 software2 software3 
2  NULL  NULL  NULL 

Если его легче сделать это один, так или иначе, это не имеет никакого значения.

+0

Вы * предпочитаете * 'customers.id' быть включенным или нет? Или производительность важнее? –

+0

Для его включения было бы лучше. – fauxgt4

ответ

2

Игнорирование клиентов, которые ничего не покупают, потому что это немного короче и быстрее:

SELECT * FROM crosstab(
    'SELECT custid, product, true FROM purchases ORDER BY 1, 2'  
    , $$VALUES ('software 1'::text), ('software 2'), ('software 3')$$) 
AS ct (custid int, software1 bool, software2 bool, software3 bool); 

Детали:

Одна небольшая трудность здесь: вам нужно добавьте значение boolean в запрос, так как его нет в таблице.

+0

- это значения, которые должны быть '('software 1' :: text), ('software 2' :: text), ('software 3' :: text)'? – fauxgt4

+1

@ fauxgt4: Вы можете это сделать, но это необязательно. Типы данных в выражении 'VALUES' определяются только первой строкой *. Дальнейшие строки принуждаются к тому же типу. –

1

Я не знаком с кросс-таблицы, но вы можете его с группой по п и выражение случая, как это (только если есть только те 3 программного обеспечения, если его неограниченная, что это решение не хорошо):

SELECT t.id, 
     max(case when s.product = 'software 1' then true end) as software1, 
     max(case when s.product = 'software 2' then true end) as software2, 
     max(case when s.product = 'software 3' then true end) as software3 
FROM customers t 
LEFT OUTER JOIN purchases s ON(t.id = s.custid) 
GROUP BY t.id 

Это также будет строка для недостающих идентификаторов.

+0

Это сработало (за исключением того, что max не работает над логическим, а вместо этого переключается на целое число 1, хотя и отлично работает). Недостатком этого было время обработки. Даже с некоторыми ограничениями на выходе он все еще был немного длинным, но мне нужен результат. Для полного запроса я планирую только одну ночь. – fauxgt4