我对PostgreSQL的tablefunc扩展中的crosstab()函数有些困惑。问题是我不希望使用标准的 Name-Category-Value 方案,而是要使用 Name-Name-Name-One-more attribute-Category-Value 这样的名称。似乎没有什么问题,但是不久我就意识到,使用我的数据库方案并没有我想的那么容易。
背景:我要使用3个表:用户, UserEvents , QuestionaryAnswers 。
因此,表如下所示:
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子句),并且由于 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
所以问题是:
答案 0 :(得分:0)
到目前为止,无需交叉表调用就可以实现您所描述的内容:
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
您可以查看结果here。