1

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

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

到目前为止,我用 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
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

(顺便说一句,第 00 列和第 24 列不太可能同时填充,除非您使用的是 25 小时制。)

于 2013-07-23T14:43:28.340 回答
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. 您可以使用PostgreSQLcrosstab()中的函数tablefunc来透视上述查询。这可能需要一些练习,但请参阅 tablefunc 文档了解如何操作。

于 2013-10-30T03:24:48.417 回答