Giải pháp theo yêu cầu
Trong khi bị mắc kẹt với thiết kế đáng tiếc này, truy vấn nhanh nhất sẽ là crosstab()
, được cung cấp bởi mô-đun bổ sung tablefunc
. Chi tiết đầy đủ trong câu trả lời liên quan này:
Đối với câu hỏi được hỏi:
SELECT * FROM crosstab(
$$SELECT e.id, ef.name, ef.value
FROM entry e
LEFT JOIN entry_fields ef
ON ef.entryid = e.id
AND ef.name = ANY ('{result,output,code,command}'::text[])
ORDER BY 1, 2$$
,$$SELECT unnest('{result,output,code,command}'::text[])$$
) AS ct (id int, result text, output text, code text, command text);
Thiết kế cơ sở dữ liệu
Nếu bạn không có khổng lồ nhiều trường khác nhau, nó sẽ đơn giản và hiệu quả hơn nhiều để hợp nhất tất cả ba bảng thành một bảng đơn giản:
Mục nhậpCREATE TABLE entry (
entry_id serial PRIMARY KEY
,field1 text
,field2 text
, ... more fields
);
Các trường không có giá trị có thể là NULL
. NULL
dung lượng lưu trữ rất rẻ (về cơ bản là 1 bit trên mỗi cột trong bitmap NULL):
- Cần bao nhiêu dung lượng đĩa để lưu trữ giá trị NULL bằng cách sử dụng postgresql DB?
- Do nullable cột chiếm thêm không gian trong PostgreSQL?
Ngay cả khi bạn có hàng trăm cột khác nhau và chỉ một vài cột được lấp đầy cho mỗi mục nhập, điều này sẽ vẫn sử dụng ít dung lượng đĩa hơn nhiều.
Truy vấn của bạn trở nên tầm thường:
SELECT entry_id, result, output, code, command
FROM enty;
Nếu bạn có quá nhiều cột và đó không chỉ là một thiết kế sai lầm (thông thường, điều này có thể được gấp lại thành ít cột hơn nhiều), hãy xem xét các loại dữ liệu hstore
hoặc json
/ jsonb
(trong Postgres 9.4) cho EAV
lưu trữ.
trang "Giới thiệu" trên mỗi Postgres :
Maximum Columns per Table 250 - 1600 depending on column types
Hãy xem xét câu trả lời có liên quan này với các lựa chọn thay thế:
Và câu hỏi này về các trường hợp / vấn đề sử dụng điển hình của cấu trúc EAV trên dba.SE: