Gunakan fungsi bawaan yang sering diabaikan width_bucket()
dalam kombinasi dengan agregasi Anda:
Jika koordinat Anda berjalan dari, katakanlah, 0 hingga 2000 dan Anda ingin menggabungkan semuanya dalam kuadrat 5 hingga satu titik, saya akan membuat petak 10 (5*2) seperti ini:
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;
Untuk meminimalkan kesalahan Anda dapat GROUP BY
kisi seperti yang ditunjukkan, tetapi simpan koordinat rata-rata aktual:
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 mendemonstrasikan keduanya secara bersamaan.
Nah, kasus khusus ini bisa lebih sederhana:
...
GROUP BY
device_id
, (pos_x / 10) * 10 -- truncates last digit of an integer
, (pos_y / 10) * 10
...
Tapi itu hanya karena ukuran kisi demo 10
cocok dengan sistem desimal. Coba hal yang sama dengan ukuran kotak 17
atau apalah...
Luaskan ke stempel waktu
Anda dapat memperluas pendekatan ini untuk mencakup date
dan timestamp
nilai dengan mengonversinya ke zaman unix (jumlah detik sejak '1970-1-1') dengan extract().
SELECT extract(epoch FROM '2012-10-01 21:06:38+02'::timestamptz);
Setelah selesai, konversikan kembali hasilnya ke timestamp with time zone
:
SELECT timestamptz 'epoch' + 1349118398 * interval '1s';
Atau cukup to_timestamp()
:
SELECT to_timestamp(1349118398);