SQL/Postgres-根据组中的行位置将每N行折叠为1
我有一组来自Postgres表的有序结果,其中每组4行表示一组相关数据。我想进一步处理这组结果,这样每一组4行都会被折叠成一行,列名称有别名,其中每一列的值都基于该行在组中的位置-我很接近,但我不能完全正确地进行查询(我也不相信我正在以最佳方式接近这一点)。以下是场景: 我正在收集调查结果-每个调查有4个问题,但每个答案都存储在数据库中的单独一行中。但是,它们通过提交SQL/Postgres-根据组中的行位置将每N行折叠为1,sql,postgresql,Sql,Postgresql,我有一组来自Postgres表的有序结果,其中每组4行表示一组相关数据。我想进一步处理这组结果,这样每一组4行都会被折叠成一行,列名称有别名,其中每一列的值都基于该行在组中的位置-我很接近,但我不能完全正确地进行查询(我也不相信我正在以最佳方式接近这一点)。以下是场景: 我正在收集调查结果-每个调查有4个问题,但每个答案都存储在数据库中的单独一行中。但是,它们通过提交事件\u id相互关联,并且结果保证以固定顺序返回。一组调查结果将类似于: event_id | answer --
事件\u id
相互关联,并且结果保证以固定顺序返回。一组调查结果将类似于:
event_id | answer
----------------------------
a | 10
a | foo
a | 9
a | bar
b | 2
b | baz
b | 4
b | zip
我想能够做的是查询这个结果,这样最终的输出会在它们自己的行中显示出每组4个结果,并带有别名的列名
event_id | score_1 | reason_1 | score_2 | reason_2
----------------------------------------------------------
a | 10 | foo | 9 | bar
b | 2 | baz | 4 | zip
我能得到的最接近的是
SELECT survey_answers.event_id,
(SELECT survey_answers.answer FROM survey_answers FETCH NEXT 1 ROWS ONLY) AS score_1,
(SELECT survey_answers.answer FROM survey_answers OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY) AS reason_1
(SELECT survey_answers.answer FROM survey_answers OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY) AS score_2,
(SELECT survey_answers.answer FROM survey_answers OFFSET 3 ROWS FETCH NEXT 1 ROWS ONLY) AS reason_2
FROM survey_answers
GROUP BY survey_answers.event_id
但可以理解的是,这返回了正确的行数,但具有相同的值(除了event\u id
):
如何构造查询,使其在每批4行中应用偏移量
/获取
行为,或者更准确地说,在每个唯一的事件id集
s中应用行为?
首先,这看起来是一个非常糟糕的设计:
没有保证的订单!数据库以随机顺序存储数据,并以随机顺序调用它们。您确实需要一个订单列。在这种小情况下,这可能适用于事故
您应该生成两列,一列表示分数,一列表示原因。把这些类型混在一起不是个好主意
不过,对于这个简单而简短的示例,这可能是一个解决方案(请记住,不建议将此用于生产表):
行编号()为每个事件id
添加行计数。在这种情况下,从1到4。这可用于识别回答的类型(参见FIDLE中的中间步骤)。在生产性代码中,您应该使用一些order列来确保顺序。然后,窗口函数看起来像是partitionbyevent\u id orderbyorder\u column
这是一个关于事件id
和类型id(行号)的简单轴心,它完全符合您的期望
首先,这看起来是一个非常糟糕的设计:
没有保证的订单!数据库以随机顺序存储数据,并以随机顺序调用它们。您确实需要一个订单列。在这种小情况下,这可能适用于事故
您应该生成两列,一列表示分数,一列表示原因。把这些类型混在一起不是个好主意
不过,对于这个简单而简短的示例,这可能是一个解决方案(请记住,不建议将此用于生产表):
行编号()为每个事件id
添加行计数。在这种情况下,从1到4。这可用于识别回答的类型(参见FIDLE中的中间步骤)。在生产性代码中,您应该使用一些order列来确保顺序。然后,窗口函数看起来像是partitionbyevent\u id orderbyorder\u column
这是一个关于事件id
和类型id(行号)的简单轴心,它完全符合您的期望
您需要一个列来指定顺序。在您的情况下,这可能是一个serial
列,它保证在每次插入时都会增加。我会把这样一个专栏称为“调查结果id”
使用此列,您可以执行以下操作:
select event_id,
max(case when seqnum = 1 then answer end) as score_1,
max(case when seqnum = 2 then answer end) as reason_1,
max(case when seqnum = 3 then answer end) as score_2,
max(case when seqnum = 4 then answer end) as reason_2
from (select sr.*,
row_number() over (partition by event_id order by survey_result_id) as seqnum
from survey_results sr
) sr
group by event_id;
如果没有这样一个列,您就无法可靠地执行所需的操作,因为SQL表表示无序集 您需要一个列来指定顺序。在您的情况下,这可能是一个
serial
列,它保证在每次插入时都会增加。我会把这样一个专栏称为“调查结果id”
使用此列,您可以执行以下操作:
select event_id,
max(case when seqnum = 1 then answer end) as score_1,
max(case when seqnum = 2 then answer end) as reason_1,
max(case when seqnum = 3 then answer end) as score_2,
max(case when seqnum = 4 then answer end) as reason_2
from (select sr.*,
row_number() over (partition by event_id order by survey_result_id) as seqnum
from survey_results sr
) sr
group by event_id;
如果没有这样一个列,您就无法可靠地执行所需的操作,因为SQL表表示无序集 在回答这个问题时,我们必须看到第三列,其中提供了
事件id
组中每个项目的顺序。@skwidbreth。“结果保证按固定顺序返回”。你不了解数据库或Postgres。表格表示无序的集合。唯一的排序方法是使用带有order by
子句的列或表达式。如果没有包含订购信息的列,则无法执行所需操作。如果没有第三列提供事件\u id
组中每个项目的订购信息,则无法回答此问题。@skwidbreth。“结果保证按固定顺序返回”。你不了解数据库或Postgres。表格表示无序的集合。唯一的排序方法是使用带有order by
子句的列或表达式。如果您没有包含订购信息的列,则无法执行所需操作。谢谢,Gordon。你说得对,我对数据库/博士后的知识有限。这不是我设计的一个表/模式,只是一个我一直坚持的,试图充分利用它的表/模式。你实际上回答了我发布的一个相关问题,其中每个字段都有一个唯一的ID-这是我理想的处理此查询的方式,但不幸的是,这些身份证可能会随着时间的推移而改变,不能一直依赖……谢谢,戈登。你说得对,我对数据库/博士后的知识有限。这不是我设计的一个表/模式,只是一个我一直坚持的,试图充分利用它的表/模式。实际上,你已经回答了我发布的一个相关问题,其中每个字段都有一个唯一的ID——这是我理想的处理此查询的方式,但不幸的是,这些ID可能会随着时间的推移而变化,无法被考虑
select event_id,
max(case when seqnum = 1 then answer end) as score_1,
max(case when seqnum = 2 then answer end) as reason_1,
max(case when seqnum = 3 then answer end) as score_2,
max(case when seqnum = 4 then answer end) as reason_2
from (select sr.*,
row_number() over (partition by event_id order by survey_result_id) as seqnum
from survey_results sr
) sr
group by event_id;