我在这里的交叉表查询中缺少什么?

ari*_*wan 7 postgresql pivot

我很难理解如何从我正在使用的数据库中正确转置此表。该表是由几年前设计数据库的人创建的,但我设法使用 检索该表的创建语句pg_dump

下面是带有示例条目的表:

CREATE TABLE response (
    session_id integer NOT NULL,
    seconds integer NOT NULL,
    question_id integer NOT NULL,
    response character varying(500),
    file bytea
);

INSERT INTO response(session_id, seconds, question_id, response, file)
VALUES (758,1459505869,31,'0',''),  (758,1459505869,32,'0',''), 
(758,1459505869,33,'0',''), (758,1459505869,34,'0',''), 
(758,1459505869,35,'1',''), (758,1459505869,36,'0',''), 
(758,1459505869,37,'0',''), (758,1459505869,38,'0',''), 
(758,1459506973,38,'0',''), (758,1459506973,37,'0',''), 
(758,1459506973,36,'0',''),(758,1459506973,35,'1',''),  
(758,1459506973,34,'0',''),(758,1459506973,33,'0',''),  
(758,1459506973,32,'0',''),(758,1459506973,31,'0',''),
(758,1459508676,31,'0',''),(758,1459508676,32,'0',''),  
(758,1459508676,33,'0',''),(758,1459508676,34,'0',''),  
(758,1459508676,35,'1',''),(758,1459508676,36,'0',''),  
(758,1459508676,37,'0', ''),    (758,1459508676,38,'0', '');

SELECT * FROM response LIMIT 5;
session_id  seconds   question_id   response    file
   758     1459505869     31           0         [null]
   758     1459505869     32           0         [null]
   758     1459505869     33           0         [null]
   758     1459505869     34           0         [null]
   758     1459505869     35           1         [null]
Run Code Online (Sandbox Code Playgroud)

该列中的问题 IDquestion_id代表以下内容:

30  -- not_foot_count 
31  -- not_moving
32  -- foot
33  -- bicycle
34  -- motorcycle
35  -- car
36  -- bus
37  -- metro
38  -- other
39  -- train
Run Code Online (Sandbox Code Playgroud)

响应可以是文本(错误的用户响应),但主要是 a1或 a 0(我感兴趣)。

所以我想将该表转置为一个新表survey,以便返回的查询结果对于每一列都有相应的响应代码值作为列名(32 -> foot; 33 -> bike; 35 -> car.etc)

我对所有这些回复不感兴趣,但对 5 : foot, bike(对于自行车)、buscar和感兴趣metro

因为我很难只检索 5 个感兴趣的响应,所以我开始检索所有这些值,看看我是否正确地做事。事实证明我做错了。

这是我的尝试:

30  -- not_foot_count 
31  -- not_moving
32  -- foot
33  -- bicycle
34  -- motorcycle
35  -- car
36  -- bus
37  -- metro
38  -- other
39  -- train
Run Code Online (Sandbox Code Playgroud)

这使:

SELECT * FROM survey;
session_id seconds not_foot_count not_moving foot bike motor car bus metro train other
758       1459505869       0          0        0   0    0     0   0   0      0     0
758       1459506973       0          0        0   0    0     0   0   0      0     0
758       1459508676       0          0        0   0    0     0   0   0      0     0
Run Code Online (Sandbox Code Playgroud)

请注意,这并不正确,因为该列car应该是正确的1

此外,我对所有的价值观都不是不感兴趣。相反,只希望存在感兴趣的值。

预计出

我希望将我的返回结果限制为以下内容(带有正确答案):

session_id  seconds    foot bike car bus metro 
    758   1459505869    0     0   1   0    0
    758   1459506973    0     0   1   0    0
    758   1459508676    0     0   1   0    0
Run Code Online (Sandbox Code Playgroud)

注意:我的尝试在此dbfiddle中进行了说明。

编辑

就评论而言,问题已编辑以显示完整的预期输出。

小智 4

我不喜欢 crosstab() 函数,因为我发现它比过滤聚合更复杂(并且它不能解决您需要手动指定所有结果列的事实)。

以下返回您想要的内容。

select session_id, 
       seconds, 
       max(response) filter (where question_id = 32) as foot,
       max(response) filter (where question_id = 33) as bike,
       max(response) filter (where question_id = 36) as bus,
       max(response) filter (where question_id = 35) as car,
       max(response) filter (where question_id = 37) as metro
from response
group by session_id, seconds
Run Code Online (Sandbox Code Playgroud)