2010-09-30 35 views
11

Tôi có một bảng như thế này để lưu kết quả kiểm tra y tế và ngày gửi báo cáo và kết quả. Trên thực tế ngày gửi được dựa trên ngày clinic_visit. Khách hàng có thể có một hoặc nhiều báo cáo (ngày có thể thay đổi)PostgreSQL: cách kết hợp nhiều hàng?

--------------------------------------- 
| 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 | 
--------------------------------------- 

Tôi muốn trích xuất báo cáo sau từ dữ liệu trên.

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

Tôi đang làm việc trên Postgresql. chức năng "crosstab" sẽ không hoạt động ở đây vì "date_sent" không nhất quán cho mỗi khách hàng.

Bất kỳ ai có thể đưa ra ý tưởng sơ bộ về cách truy vấn?

Trả lời

14

tôi đề nghị các phương pháp sau đây:

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

Nó không phải chính xác định dạng đầu ra tương tự, nhưng nó sẽ cung cấp cho bạn những thông tin tương tự nhanh hơn và sạch hơn nhiều.

Nếu bạn muốn các kết quả trong các cột riêng biệt, bạn luôn có thể làm điều này:

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; 

mặc dù đó rõ ràng là sẽ giới thiệu một số mã hóa cứng của kết quả càng tốt.

+0

Giải pháp của bạn hoạt động nhưng tôi nghĩ OP muốn dữ liệu được lập bảng như trong câu hỏi, để dễ dàng xem nơi trống mục (ví dụ 1 khách hàng không có kết quả E). – SabreWolfy

+2

@SabreWolfy: cập nhật –

+3

Câu trả lời này giải quyết được vấn đề và phải được OP chấp nhận. – SabreWolfy

0

Trong khi tôi đang đọc về "mô phỏng hàng số", tôi đã cố gắng tìm ra một cách khác để thực hiện việc này.

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; 

nhưng truy vấn mất 10 phút (500.000 ms ++). cho 30.000 hồ sơ. Đây là quá dài ..

+0

Sử dụng GIẢI THÍCH ANALAYZE để xem cách truy vấn được thực hiện và chỉ mục nào được sử dụng. client_id không cần chỉ mục. –

+0

Cảm ơn Frank .. Tôi đã lập chỉ mục "client_id" và giờ nó chạy dưới 5000 mili giây. – thinzar00

+2

Với Postgres bạn không cần phải "mô phỏng" hàng số. Chức năng này có sẵn từ 8.4 (và nếu bạn đang sử dụng phiên bản cũ hơn tôi khuyên bạn nên nâng cấp càng sớm càng tốt) –

Các vấn đề liên quan