【发布时间】:2018-12-22 02:12:22
【问题描述】:
我对 PostgreSQL 的 tablefunc 扩展中的 crosstab() 函数有点困惑。问题是我想要的不是标准的Name-Category-Value 方案,而是Name-Attribute of Name-One more attribute-Category-Value。这似乎不是问题,但很快我就意识到,使用我的 DB 方案,它不会像我想象的那么容易。
背景:我要使用 3 个表:Users、UserEvents、QuestionaryAnswers。
- Users 表包含人员
- UserEvents 包含与此人发生的事件(FK 引用用户)
- 和 QuestionaryAnswers,其中包含对通过 FK 引用 UserEventId 的问题的答案。
所以,表格看起来像这样:
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);
用户事件:
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 子句),并且因为UserEvents 表中的 Status 属性也将被随机选择。我想看到的是由 EventId 派生的单独的 UserEventId 和 Status 字段,因此会有 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”,但我还需要在“UserEvents”Status 字段和“用户”GroupId 字段,所以我需要表格内的 EventID 或 Status。我是否错过了一些更简单的机会或在交叉表中显示这些数据的能力? P.S 我使用的是 PostgreSQL 11.1
【问题讨论】:
-
是的,你写的我不明白你为什么要进行交叉连接
-
所以我稍微编辑了我的问题以获得某种形式的预期结果。现在可以了吗?
-
如果您可以简单地将您想要获取的表格样本放在这里,您的目标会更加清晰
-
请同时显示表格“AnswerItems”
-
我设置了一个 dbfiddle(在没有交叉表的情况下实现了你的结果)dbfiddle.uk/… 但我真的不明白你的问题是什么。然而:最后一列中的“144”值是从哪里来的?
标签: sql postgresql crosstab