使用经常被忽视的内置函数
width_bucket()
与聚合函数结合使用:
如果您的坐标从0到2000,希望将每个5个单位的正方形内的所有内容合并为一个点,我会按照以下方式布置一个10个(5*2)的网格:
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
FROM tbl
GROUP BY 1,2,3
ORDER BY 1,2,3;
为了
减少误差,您可以按照以下示例对网格进行
GROUP BY
操作,并保存实际的平均坐标:
SELECT device_id
, avg(pos_x)::int AS pos_x
, avg(pos_y)::int AS pos_y
, count(*) AS ct
FROM tbl
GROUP BY
device_id
, width_bucket(pos_x, 0, 2000, 2000/10) * 10
, width_bucket(pos_y, 0, 2000, 2000/10) * 10
ORDER BY 1,2,3;
这里有一个sqlfiddle示例,可以同时演示两种情况。
嗯,这个特定的情况可能会更简单:
...
GROUP BY
device_id
, (pos_x / 10) * 10 -- truncates last digit of an integer
, (pos_y / 10) * 10
...
但这只是因为演示的网格大小为10
方便地匹配了十进制系统。尝试使用网格大小为17
等其他大小...
扩展到时间戳
您可以通过使用extract()将date
和timestamp
值转换为Unix时期(自1970年1月1日以来的秒数)来扩展此方法。
SELECT extract(epoch FROM '2012-10-01 21:06:38+02'::timestamptz);
完成后,将结果转换回带时区的时间戳 (timestamp with time zone
):
SELECT timestamptz 'epoch' + 1349118398 * interval '1s';
或者简单地使用
to_timestamp()
函数:
SELECT to_timestamp(1349118398);