用for循环替换多个左连接

时间:2013-07-23 14:03:32

标签: postgresql loops join

我有一个表格,每个点都有一个时间属性(列“小时”),位于砂砾的不同方格(由“gridid”列标记)。

对于每个方格,我想获得按小时分组的点数,从而获得一个包含24列+与现有gridid一样多的行的表。

到目前为止,我用24个左连接(下图)做到了这一点。有没有办法用简单的循环来简化查询?

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

2 个答案:

答案 0 :(得分: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

(顺便说一句,第00和第24列不太可能都填充,除非你每天使用25小时。)

答案 1 :(得分:0)

一般来说,我同意用for循环替换任何类型的连接几乎总是一个坏主意。当PostgreSQL是最合适的加入方法时,它将使用循环。特别是,FOR循环不会为您提供普通连接所不具备的功能,这意味着规划人员可以在自己完成的工作中对计划程序进行微观管理。

现在,在您的情况下,您不需要循环。你有三个选择。

  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文档 怎么做。