Sử dụng hàm tích hợp thường bị bỏ qua width_bucket()
kết hợp với tổng hợp của bạn:
Nếu tọa độ của bạn chạy từ 0 đến 2000 và bạn muốn hợp nhất mọi thứ trong các ô vuông từ 5 đến điểm đơn lẻ, tôi sẽ bố trí một lưới 10 (5 * 2) như thế này:
SELECT device_id
, width_bucket(pos_x, 0, 2000, 2000/10) * 10 AS pos_x
, width_bucket(pos_y, 0, 2000, 2000/10) * 10 AS pos_y
, count(*) AS ct -- or any other aggregate
FROM tbl
GROUP BY 1,2,3
ORDER BY 1,2,3;
Để giảm thiểu lỗi bạn có thể GROUP BY
lưới như được minh họa, nhưng lưu tọa độ trung bình thực tế:
SELECT device_id
, avg(pos_x)::int AS pos_x -- save actual averages to minimize error
, avg(pos_y)::int AS pos_y -- cast if you need to
, count(*) AS ct -- or any other aggregate
FROM tbl
GROUP BY
device_id
, width_bucket(pos_x, 0, 2000, 2000/10) * 10 -- aggregate by grid
, width_bucket(pos_y, 0, 2000, 2000/10) * 10
ORDER BY 1,2,3;
sqlfiddle thể hiện cả hai bên cạnh.
Chà, trường hợp cụ thể này có thể đơn giản hơn:
...
GROUP BY
device_id
, (pos_x / 10) * 10 -- truncates last digit of an integer
, (pos_y / 10) * 10
...
Nhưng đó chỉ là do kích thước lưới demo của 10
phù hợp với hệ thống thập phân một cách thuận tiện. Hãy thử tương tự với kích thước lưới là 17
hoặc cái gì đó ...
Mở rộng đến dấu thời gian
Bạn có thể mở rộng phương pháp này để bao gồm date
và timestamp
bằng cách chuyển đổi chúng thành kỷ nguyên unix (số giây kể từ '1970-1-1') với extract ().
SELECT extract(epoch FROM '2012-10-01 21:06:38+02'::timestamptz);
Khi bạn hoàn tất, hãy chuyển đổi kết quả trở lại timestamp with time zone
:
SELECT timestamptz 'epoch' + 1349118398 * interval '1s';
Hoặc đơn giản là to_timestamp()
:
SELECT to_timestamp(1349118398);