1

私は、グリットの異なる正方形(列「グリッド」でマークされている)にある時間属性(列「時間」)を持つポイントを持つテーブルを持っています。

各正方形について、時間ごとにグループ化された範囲内にあるポイントの数を取得したいので、24 列 + 既存のグリッド ID と同じ数の行を持つテーブルを取得します。

これまでのところ、24 個の leftjoin でそれを行いました (以下)。単純なループでクエリを単純化する方法はありますか?

SELECT * from (select gridid, count(id)  as "00" from points where hour = 0 GROUP BY gridid ORDER BY "00" DESC)t00 

left join
(select gridid, count(id)  as "01" from points where hour = 1 GROUP BY gridid)t01
on t01.gridid = t00.gridid

left join
(select gridid, count(id)  as "02" from points where hour = 2 GROUP BY gridid)t02
on t02.gridid = t00.gridid

...

left join
(select gridid, count(id)  as "24" from points where hour = 24 GROUP BY gridid)t02
on t02.gridid = t24.gridid
4

2 に答える 2

1

FOR ループは一般的に、SQL では悪い考えです。これは、セットベースの演算子でうまく機能します。代わりに、次のようにしてみてください。

select grid_id,
       sum(case hour when 0 then 1 end) as "00",
       sum(case hour when 1 then 1 end) as "01",
       sum(case hour when 2 then 1 end) as "02",
...

       sum(case hour when 24 then 1 end) as "24"
from points 
group by grid_id
order by 2 desc

(ちなみに、25 時間制を使用していない限り、列 00 と 24 の両方が入力されることはほとんどありません。)

于 2013-07-23T14:43:28.340 に答える
0

一般に、あらゆる種類の結合を for ループに置き換えることは、ほとんどの場合、悪い考えであることに同意します。PostgreSQL は、結合の最も適切な方法である場合にループを使用します。特に、FOR ループは、通常の結合では得られないものを何も提供しません。これは、プランナーが単独で完全に実行できるジョブでプランナーを細かく管理することを意味します。

あなたの場合、ループは必要ありません。3 つのオプションがあります。

  1. 上記の Mark Ba​​nnister が示唆する方法で CASE を使用できます。

  2. セットを返し、クライアントでピボットするだけです。何かのようなもの

       SELECT grid_id, count(id), hour 
         FROM points
     GROUP BY grid_id, hour
     ORDER BY grid_id, hour;
    
  3. crosstab()の関数を使用してtablefunc、PostgreSQL で上記のクエリをピボットできます。これには多少の練習が必要ですが、方法については tablefunc のドキュメントを参照してください。

于 2013-10-30T03:24:48.417 に答える