PostgreSQL:如何组合多行?

时间:2010-09-30 02:59:59

标签: sql postgresql

我有一张这样的表来保存体检结果和发送报告的日期以及结果。实际上发送的日期是基于clinic_visit日期。客户可以有一个或多个报告(日期可能不同)

---------------------------------------
|  client_id  |  date_sent  | result |
---------------------------------------
| 1           |   2001      |    A   |
| 1           |   2002      |    B   |
| 2           |   2002      |    D   |
| 3           |   2001      |    A   |
| 3           |   2003      |    C   |
| 3           |   2005      |    E   |
| 4           |   2002      |    D   |
| 4           |   2004      |    E   |
| 5           |   2004      |    B   |
---------------------------------------

我想从以上数据中提取以下报告。

---------------------------------------------------
|  client_id  |  result1  |  result2  |   resut3  |
---------------------------------------------------
|      1      |    A      |    B      |           |
|      2      |    D      |           |           |
|      3      |    A      |    C      |     E     |
|      4      |    D      |    E      |           |
|      5      |    B      |           |           |
---------------------------------------------------

我正在研究Postgresql。 “交叉表”功能在此处不起作用,因为每个客户端的“date_sent”不一致。

任何人都可以大致了解应该如何查询?

2 个答案:

答案 0 :(得分:15)

我建议采用以下方法:

SELECT client_id, array_agg(result) AS results
    FROM labresults
    GROUP BY client_id;

它的输出格式并不完全相同,但它可以更快,更清晰地为您提供相同的信息。

如果您希望将结果放在不同的列中,您可以随时执行此操作:

SELECT client_id,
       results[1] AS result1,
       results[2] AS result2,
       results[3] AS result3
FROM
(
    SELECT client_id, array_agg(result) AS results
        FROM labresults
        GROUP BY client_id 
) AS r
ORDER BY client_id;

虽然这显然会引入一些硬编码的可能结果。

答案 1 :(得分:0)

当我读到“模拟row_number”时,我试图想出另一种方法来做到这一点。

SELECT client_id,  
       MAX( CASE seq WHEN 1 THEN result ELSE '' END ) AS result1,  
       MAX( CASE seq WHEN 2 THEN result ELSE '' END ) AS result2,  
       MAX( CASE seq WHEN 3 THEN result ELSE '' END ) AS result3,  
       MAX( CASE seq WHEN 4 THEN result ELSE '' END ) AS result4,  
       MAX( CASE seq WHEN 5 THEN result ELSE '' END ) AS result5  
FROM ( SELECT p1.client_id, 
              p1.result,  
              ( SELECT COUNT(*)  
                FROM labresults p2  
                WHERE p2.client_id = p1.client_id  
                AND p2.result <= p1.result )  
       FROM labresults p1 
) D ( client_id, result, seq )  
GROUP BY client_id;  

但查询花了10分钟(500,000 ms ++)。 30,000条记录。这太长了..