3

次の単純化された構造を持つ PostgreSQL データベース テーブルがあります。

  • デバイス ID varchar
  • Pos_X (整数)
  • Pos_Y (整数)

基本的に、このテーブルには、デバイスの 2 次元のウェイポイント データが多数含まれています。ここで、出力の座標数を減らすクエリを設計したいと考えています。近くの座標を集約する必要があります (特定の x、y しきい値について) 例:

行 1: DEVICE1;603;1205

行 2: DEVICE1;604;1204

しきい値が 5 の場合、分散が 5 より小さいため、これら 2 つの行を集計する必要があります。PostgreSQL または SQL で一般的にこれを行う方法はありますか?

4

2 に答える 2

9

見過ごされがちな組み込み関数width_bucket()を集計と組み合わせて使用​​します。

たとえば、座標が 0 から 2000 まであり、5 の正方形内のすべてを 1 つの点に統合したい場合、次のように 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 -- or any other aggregate
FROM   tbl
GROUP  BY 1,2,3
ORDER  BY 1,2,3;

エラーを最小限に抑えるには、実際GROUP BYの平均座標を保存します。

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。

まあ、この特定のケースはもっと簡単かもしれません:

...
GROUP  BY
       device_id
     , (pos_x / 10) * 10          -- truncates last digit of an integer
     , (pos_y / 10) * 10
...

しかし、これはデモ グリッドのサイズが1010 進法と都合よく一致しているからです。または何かのグリッドサイズで同じことを試してください17...


タイムスタンプに展開

extract()を使用して unix エポック ('1970-1-1' からの秒数) に変換することで、このアプローチをカバーdateと値に拡張できます。timestamp

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);
于 2012-09-28T14:45:08.903 に答える
1
select [some aggregates] group by (pos_x/5, pos_y/5); 

5の代わりに、必要な集計の量に応じて任意の数を使用できます/

于 2012-09-28T14:17:53.027 に答える