запрос кросс-таблицы дает неожиданные результаты - PullRequest
0 голосов
/ 21 декабря 2018

Меня немного смутила функция crosstab () внутри расширения tablefunc в PostgreSQL.Проблема в том, что мне нужна не стандартная Имя-Категория-Значение , а что-то вроде Имя-Атрибут имени-Еще один атрибут-Категория-значения .Это не казалось проблемой, но вскоре я понял, что с моей схемой БД это будет не так просто, как я думал.

Справочная информация: у меня есть 3 таблицы, которые я хочу использовать: Пользователи , UserEvents , QuestionaryAnswers .

  1. Таблица Users содержит людей
  2. UserEvents содержит события, которые произошли с этими людьми (со ссылкой на FK для пользователей)
  3. и QuestionaryAnswers, который содержит ответы на вопросы, которыессылка на UserEventId через FK.

Итак, таблицы выглядят так:

create table "Users"("Id" int, "AttrId" int, "GroupId" int);
create table "UserEvents"("Id" int, "UserId" int, "Status" varchar(20), "EventId" int);
create table "QuestionaryAnswers"("UserEventId" int, "QuestionaryItemId" int, "AnswerItemId" int);

Пользователи:

INSERT INTO "public"."Users"("Id", "AttrId", "GroupId") 
VALUES (1, 1, 12587), (2, 1, 11092);

UserEvents:

INSERT INTO "public"."UserEvents"("Id", "UserId", "Status", "EventId") 
VALUES (142, 1, 'Checked', 2), (143, 1, 'Created', 1), (144, 2, 'Done', 2);

И Ответы на вопросники:

INSERT INTO "public"."QuestionaryAnswers"("UserEventId", "QuestionaryItemId", "AnswerItemId") 
VALUES ('142', 1, 2),
('142', 4, 16),
('142', 5, 25),
('143', 12, 99);
('144', 12, 100);

Ну, вот тут и возникают проблемы.Это мой перекрестный запрос на данный момент:

SELECT *
FROM crosstab(' SELECT "UserEvents"."UserId", "QuestionaryAnswers"."UserEventId", "Users"."AttrId", "Users"."GroupId", "QuestionaryAnswers"."QuestionaryItemId", "AnswerItems"."Name"
 FROM "QuestionaryAnswers"
    LEFT JOIN "AnswerItems" ON "QuestionaryAnswers"."AnswerItemId" = "AnswerItems"."Id" 
    LEFT JOIN "UserEvent" ON "QuestionaryAnswers"."UserEventId" = "UserEvents"."Id" 
    LEFT JOIN "Users" ON "UserEvents"."UserId" = "Users"."Id"
    ORDER BY 1, 2'::text, 
'SELECT 1 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12 UNION SELECT 13 UNION SELECT 14 UNION SELECT 15 UNION SELECT 16 UNION SELECT 17 UNION SELECT 18 UNION SELECT 20 UNION SELECT 21 ORDER BY 1'::text) 
crosstab("UserId" integer, "UserEventId" uuid,
"AttrId" integer, "GroupId" integer,
"Question1" text, "2" text, "3" text, "4" text,
"5" text, "6" text, "7" text, "8" text, "9" text,
"10" text, "11" text, "12" text, "13" text, "14" text,
"15" text, "16" text, "17" text, "18" text, "19" text)

И здесь все кажется довольно простым, за исключением одной маленькой детали - категории \ столбцы \ вопросы связаны с различными UserEventId , поэтому в основномUserEventId выбирается случайным образом (согласно предложению ORDER), и из-за этого атрибута Status из таблицы UserEvents также выбирается случайным образом.То, что я хочу видеть, это отдельные поля UserEventId и Status, которые получены из EventId , поэтому будут UserEventId_1 и UserEventId_2 ID, и, вероятно, также связанные поля,например, Status_1 и Status_2 , например:

UserId | UserEventId_EventId1 | UserEventId_EventId2 | AttrId | GroupId | Question1 | Question3 | Question4 | Question5 | Question12
-------+----------------------+----------------------+--------+---------+-----------+-----------+-----------+-----------+-----------
     1 |                  143 |                  142 |      1 |   12587 |           |           |        16 |        25 |         99
     2 |                      |                  144 |      1 |   11092 |           |           |           |           |        144

Итак, вопросы:

  1. Как я могу сделать категорию"столбец кросс-таблицы на основе значения внешнего ключа?Я не могу понять это, возможно, потому что это разные «стопки» категорий - события и вопросы.
  2. Сама идея в этом несколько ошибочна - кросс-таблица не предназначена для отображения данных в формате, который яхочу, поэтому я опишу цель.Мне нужна таблица для выполнения простых сравнительных запросов «сколько людей ответили на вопрос 1, как это, и ответили на вопрос 2, как это», но мне также нужно отфильтровать это в поле «UserEvents» Status и «Users»" GroupId , поэтому мне нужно либо EventID, либо Status внутри таблицы.Я упускаю какую-то возможность сделать это проще или возможность показывать эти данные в кросс-таблице?PS Я использую PostgreSQL 11.1

1 Ответ

0 голосов
/ 21 декабря 2018

Пока что то, что вы описали, может быть достигнуто без вызова кросс-таблицы:

select u1."Id" as "UserId", u1."GroupId", e1."Status", 
    q1."QuestionaryItemId", q1."AnswerItemId", count(*)
from "Users" u1
left join "UserEvents" e1
on u1."Id" = e1."UserId"
left join "QuestionaryAnswers" q1
on q1."UserEventId"=e1."Id"
group by 1,2,3,4,5

Вы можете проверить результат здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...