Một vài truy vấn được kiểm tra và tối ưu hóa cho Postgres 9.3. Tất cả đều trả về như nhau, tất cả về cơ bản là SQL tiêu chuẩn, nhưng không có RDBMS nào hỗ trợ tiêu chuẩn hoàn toàn.
Cụ thể, cái đầu tiên sử dụng a LATERAL JOIN
, cái bị thiếu trong Oracle hoặc MySQL. Kiểm tra mà thực hiện tốt nhất.
Tất cả đều sử dụng quét chỉ mục trên lookup
bảng trong Postgres. Rõ ràng, lookup.nominal_value
cần phải được lập chỉ mục. Tôi đề nghị làm cho nó UNIQUE
bởi vì có vẻ như cột phải là duy nhất và bởi vì điều đó cũng tự động tạo ra chỉ mục quan trọng.
THAM GIA
SELECT m.id, m.measurement, l.nominal_value
FROM measurement m
JOIN LATERAL (
(
SELECT nominal_value - m.measurement AS diff, nominal_value
FROM lookup
WHERE nominal_value >= m.measurement
ORDER BY nominal_value
LIMIT 1
)
UNION ALL
(
SELECT m.measurement - nominal_value, nominal_value
FROM lookup
WHERE nominal_value <= m.measurement
ORDER by nominal_value DESC
LIMIT 1
)
ORDER BY 1 -- NULLS LAST is default
LIMIT 1
) l ON TRUE;
Tất cả các dấu ngoặc đơn cần thiết cho UNION
. Câu trả lời liên quan:
Postgres 9.2 chọn nhiều hàng cụ thể trong một truy vấn
Truy vấn con tương quan trong một truy vấn con
SELECT id, measurement
,CASE WHEN hi - measurement > measurement - lo
THEN lo
ELSE COALESCE(hi, lo) -- cover all possible NULL values
END AS nominal_value
FROM (
SELECT id, measurement
,(SELECT nominal_value
FROM lookup
WHERE nominal_value >= m.measurement
ORDER BY nominal_value
LIMIT 1) AS hi
,(SELECT nominal_value
FROM lookup
WHERE nominal_value <= m.measurement
ORDER by nominal_value DESC
LIMIT 1) AS lo -- cover possible NULL values
FROM measurement m
) sub;
Các truy vấn con tương quan trong CTE
WITH cte AS (
SELECT id, measurement
,(SELECT nominal_value
FROM lookup
WHERE nominal_value >= m.measurement
ORDER BY nominal_value
LIMIT 1) AS hi
,(SELECT nominal_value
FROM lookup
WHERE nominal_value <= m.measurement
ORDER by nominal_value DESC
LIMIT 1) AS lo
FROM measurement m
)
SELECT id, measurement
,CASE WHEN hi - measurement > measurement - lo
THEN lo
ELSE COALESCE(hi, lo) -- cover all possible NULL values
END AS nominal_value
FROM cte;
Các truy vấn con tương quan lồng nhau
SELECT id, measurement
,(SELECT nominal_value FROM (
(
SELECT nominal_value - m.measurement, nominal_value
FROM lookup
WHERE nominal_value >= m.measurement
ORDER BY nominal_value
LIMIT 1
)
UNION ALL
(
SELECT m.measurement - nominal_value, nominal_value
FROM lookup
WHERE nominal_value <= m.measurement
ORDER by nominal_value DESC
LIMIT 1
)
ORDER BY 1
LIMIT 1
) sub
) AS nominal_value
FROM measurement m;
Câu đố SQL.