WITH
cho phép bạn xác định "bảng tạm thời" để sử dụng trong truy vấn SELECT
. Ví dụ, tôi gần đây đã viết một truy vấn như thế này, để tính toán thay đổi giữa hai bộ:
-- Let o be the set of old things, and n be the set of new things.
WITH o AS (SELECT * FROM things(OLD)),
n AS (SELECT * FROM things(NEW))
-- Select both the set of things whose value changed,
-- and the set of things in the old set but not in the new set.
SELECT o.key, n.value
FROM o
LEFT JOIN n ON o.key = n.key
WHERE o.value IS DISTINCT FROM n.value
UNION ALL
-- Select the set of things in the new set but not in the old set.
SELECT n.key, n.value
FROM o
RIGHT JOIN n ON o.key = n.key
WHERE o.key IS NULL;
Bằng việc xác định các "bảng" o
và n
ở phía trên, tôi đã có thể tránh lặp lại các từ ngữ things(OLD)
và things(NEW)
.
Chắc chắn, chúng tôi có thể loại bỏ UNION ALL
bằng cách sử dụng FULL JOIN
, nhưng tôi không thể làm điều đó trong trường hợp cụ thể của mình.
Nếu tôi hiểu câu hỏi của bạn một cách chính xác, nó thực hiện điều này:
Tìm hàng lâu đời nhất ở global.prospect có tình trạng là 'mới' hay 'reset'.
Đánh dấu nó bằng cách thêm một dấu hoa thị để tình trạng của nó
Return hàng (bao gồm tinh chỉnh của chúng tôi để status
).
Tôi không nghĩ rằng WITH
sẽ đơn giản hóa mọi thứ trong trường hợp của bạn. Nó có thể là một chút thanh lịch hơn để sử dụng một điều khoản FROM
, mặc dù:
update global.prospect psp
set status = status || '*'
from (select psp_id
from global.prospect
where status = 'new' or status = 'reset'
order by request_ts
limit 1
) p2
where psp.psp_id = p2.psp_id
returning psp.*;
chưa được kiểm tra. Cho tôi biết nếu nó hoạt động.
Đó là khá nhiều chính xác những gì bạn có đã có, ngoại trừ:
này có thể dễ dàng mở rộng để cập nhật nhiều hàng. Trong phiên bản của bạn, sử dụng biểu thức truy vấn con, truy vấn sẽ không thành công nếu truy vấn con được thay đổi để mang lại nhiều hàng.
Tôi không bí danh global.prospect
trong truy vấn con, do đó dễ đọc hơn một chút. Vì điều này sử dụng mệnh đề FROM
, bạn sẽ gặp lỗi nếu vô tình tham chiếu bảng đang được cập nhật.
Trong phiên bản của bạn, khái niệm subquery được gặp cho mỗi mục duy nhất. Mặc dù PostgreSQL nên tối ưu hóa này và chỉ đánh giá sự biểu hiện một lần, tối ưu hóa này sẽ biến mất nếu bạn vô tình tham khảo một cột trong psp
hoặc thêm một biểu hiện không ổn định.
Nguồn
2012-01-04 04:06:02
Theo tài liệu, sử dụng 'WITH [RECURSIVE]' ở trên các câu lệnh 'INSERT' và' UPDATE' đã được thêm vào trong PostgreSQL 9.1. –
@JoeyAdams - sử dụng với dml - một lớp khác của hành tây để hiểu –