Nếu trường hợp của bạn đơn giản như các giá trị mẫu đề xuất, hãy câu trả lời của @Giorgos phục vụ tốt.
Tuy nhiên, đó thường không phải như vậy . Nếu id
cột là một serial
, bạn không thể dựa vào giả định rằng một hàng có time
sớm hơn cũng có id
nhỏ hơn .
Ngoài ra, time
giá trị (hoặc timestamp
như bạn có thể có) có thể dễ dàng bị trùng lặp, bạn cần đặt thứ tự sắp xếp rõ ràng.
Giả sử cả hai đều có thể xảy ra và bạn muốn id
từ hàng có time
sớm nhất trên mỗi lát thời gian (thực tế là nhỏ nhất id
trong thời gian sớm nhất , có thể có ràng buộc), truy vấn này sẽ giải quyết tình huống đúng:
SELECT *
FROM (
SELECT DISTINCT ON (way, grp)
id, way, time AS time_from
, max(time) OVER (PARTITION BY way, grp) AS time_to
FROM (
SELECT *
, row_number() OVER (ORDER BY time, id) -- id as tie breaker
- row_number() OVER (PARTITION BY way ORDER BY time, id) AS grp
FROM table1
) t
ORDER BY way, grp, time, id
) sub
ORDER BY time_from, id;
-
ORDER BY time, id
rõ ràng. Giả sử thời gian là không duy nhất, thêm idid
để tránh kết quả tùy ý - có thể thay đổi giữa các truy vấn theo cách lén lút. -
max(time) OVER (PARTITION BY way, grp)
:không cóORDER BY
, khung cửa sổ trải dài tất cả các hàng của PARTITION, vì vậy chúng tôi nhận được giá trị tối đa tuyệt đối trên mỗi lát thời gian. -
Lớp truy vấn bên ngoài chỉ cần thiết để tạo ra thứ tự sắp xếp mong muốn trong kết quả, vì chúng ta bị ràng buộc với một
ORDER BY
khác trong truy vấn consub
bằng cách sử dụngDISTINCT ON
. Chi tiết:
SQL Fiddle trình bày trường hợp sử dụng.
Nếu bạn đang tìm cách tối ưu hóa hiệu suất, hàm plpgsql có thể nhanh hơn trong trường hợp như vậy. Câu trả lời có liên quan chặt chẽ:
Ngoài ra:không sử dụng tên loại cơ bản time
làm định danh (cũng là từ dành riêng trong SQL chuẩn ).