【问题标题】:crosstab query provides unexpected results交叉表查询提供了意想不到的结果
【发布时间】:2018-12-22 02:12:22
【问题描述】:

我对 PostgreSQL 的 tablefunc 扩展中的 crosstab() 函数有点困惑。问题是我想要的不是标准的Name-Category-Value 方案,而是Name-Attribute of Name-One more attribute-Category-Value。这似乎不是问题,但很快我就意识到,使用我的 DB 方案,它不会像我想象的那么容易。

背景:我要使用 3 个表:UsersUserEventsQuestionaryAnswers

  1. Users 表包含人员
  2. UserEvents 包含与此人发生的事件(FK 引用用户)
  3. 和 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_1UserEventId_2 ID,并且可能链接字段,例如 Status_1Status_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 字段和“用户”GroupId 字段,所以我需要表格内的 EventID 或 Status。我是否错过了一些更简单的机会或在交叉表中显示这些数据的能力? P.S 我使用的是 PostgreSQL 11.1

【问题讨论】:

  • 是的,你写的我不明白你为什么要进行交叉连接
  • 所以我稍微编辑了我的问题以获得某种形式的预期结果。现在可以了吗?
  • 如果您可以简单地将您想要获取的表格样本放在这里,您的目标会更加清晰
  • 请同时显示表格“AnswerItems”
  • 我设置了一个 dbfiddle(在没有交叉表的情况下实现了你的结果)dbfiddle.uk/… 但我真的不明白你的问题是什么。然而:最后一列中的“144”值是从哪里来的?

标签: sql postgresql crosstab


【解决方案1】:

到目前为止,您所描述的可能无需交叉表调用即可实现:

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

【讨论】:

  • 但这绝对不是我想要的——在上面的示例中,我展示了我想将每个问题表示为一个单独的列,因此我将有一种简单的方法来运行带有“WHERE question1”等条件的查询=“某事”和问题2 =“某事_其他”“。这很重要,因为该表显示在 GUI SQL 工具中
  • 在看到您更新的问题之前我已经回答了。我的解决方案显然满足了最初的要求(按用户、问题、相应答案的数量划分)。但是,使用...where "QuestionaryItemId"=... 对我的查询返回的数据集运行查询没有问题。此外,我担心 EventId 和 QuestionId 的这种“双重旋转”可能需要两个相应的交叉表,然后将它们连接在一起,因为馈送到crosstab() 的 sql 查询需要分别具有行键、条件和值的三列。跨度>
  • 我明白了...好吧,我会尝试让交叉表加入交叉表然后报告结果,但这似乎不是一个很好的\干净的解决方案,如果有更方便的方法我会很高兴发现他们
猜你喜欢
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-19
  • 2017-01-05
  • 2021-10-14
相关资源
最近更新 更多