Запрос с динамическими целевыми столбцами - PullRequest
0 голосов
/ 29 мая 2018

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

У меня есть таблица названий предметов - скажем, есть 5 предметов:

fruits

id | name
1  | banana
2  | orange
3  | pear
4  | apple
5  | grape

Я тогдаесть список людей

people

id  |  name
1   |  Joe Blow
2   |  Sally Smith
3   |  John Jones
4   |  Sam Benny
5   |  Nick Stevens
6   |  Peter Sandwitch
7   |  Sarah Morgan

У меня есть третья таблица, связывающая два вышеупомянутых:

people_fruits

person_id | fruit_id
1         | 1
1         | 2
1         | 3
1         | 4
2         | 1
2         | 3
3         | 5
6         | 3
7         | 3
7         | 4

То, что я пытаюсь сделать, - это возможность динамически создавать представление, используя вышеизложенное, которое будет изменять столбцы в зависимости от содержимого таблицы фруктов.например, я хотел бы, чтобы представление показывало вышеуказанные данные следующим образом:

my_fruity_view

name            | bananna | orange | pear | apple | grape
Joe Blow        | X       | X      | X    | X     |
Sally Smith     | X       |        | X    |       |
John Jones      |         |        |      |       | X
Sam Benny       |         |        |      |       |
Nick Stevens    |         |        |      |       |
Peter Sandwitch |         |        | X    |       |
Sarah Morgan    |         |        | X    | X     |

Тогда, если бы я должен был добавить фруктовое манго позже, следующееКогда запрос был выполнен (без изменения), он добавил бы в виде столбца:

my_fruity_view

name            | bananna | orange | pear | apple | grape | mango
Joe Blow        | X       | X      | X    | X     |       |
Sally Smith     | X       |        | X    |       |       |
John Jones      |         |        |      |       | X     |
Sam Benny       |         |        |      |       |       |
Nick Stevens    |         |        |      |       |       |
Peter Sandwitch |         |        | X    |       |       |
Sarah Morgan    |         |        | X    | X     |       |

Возможен ли такой запрос?Я вижу несколько таких вещей при переполнении стека, но кажется, что это делается для каждого столбца, но мои данные должны быть динамическими.

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

1 Ответ

0 голосов
/ 29 мая 2018

В основном вам нужна таблица pivot или кросс-табуляция .Дополнительный модуль tablefunc обеспечивает необходимую вам функциональность.Если вы не знакомы с ним, сначала прочтите это:

Особая сложность вашего случая: сначала вам нужнозапрос, соединяющий таблицы для получения правильного ввода:

SELECT p.name, f.name, text 'x' AS marker -- required, logically redundant column
FROM   people             p
LEFT   JOIN people_fruits pf ON pf.person_id = p.id  -- LEFT JOIN !
LEFT   JOIN fruits        f  ON f.id = pf.fruit_id
ORDER  BY p.id, f.id;  -- seems to be the desired sort order

LEFT [OUTER] JOIN, чтобы вы не потеряли людей без фруктов.

Используйте его в функции crosstab(), принимая два параметра, подобные этому:

SELECT * FROM crosstab(
    $$SELECT p.name, f.name, text 'x'
      FROM   people             p
      LEFT   JOIN people_fruits pf ON pf.person_id = p.id
      LEFT   JOIN fruits        f  ON f.id = pf.fruit_id
      ORDER  BY p.id$$   
   ,$$VALUES ('bananna'), ('orange'), ('pear'), ('apple'), ('grape')$$)
AS ct (name text, bananna text, orange text, pear text, apple text, grape text);

Порядок фруктов в списке целевых столбцов должен соответствовать порядку фруктов во 2-м параметре (в вашем случае - id).

Пропавшие фрукты получают значение NULL.

Однако, это не динамический , пока.Полностью динамически невозможно с SQL, который требует знать результирующие столбцы во время вызова.Так или иначе, вам нужно две поездки туда и обратно на сервер БД.Вы можете позволить Postgres динамически построить запрос кросс-таблицы и затем выполнить его на следующем шаге.

Связанные ответы с примерами кода:

Альтернатива будет возвращать массив или тип документа (json, xml, ...), что содержит динамический список элементов.

...