我从停车计时器获得实时数据,并希望将停车计时器当前状态与历史数据进行比较。我的数据包含停车票,其中datetime_start用于购买时间,datetime_stop用于何时无用。
这个SQL实际工作,但非常慢。我想我会以某种方式遍历所有数据,或者可以优化其他一些事情:
(SELECT "parking_meter_id", SUM(CASE WHEN Now() BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) < (
SUM(CASE WHEN Now() - interval '1 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) +
SUM(CASE WHEN Now() - interval '2 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) +
SUM(CASE WHEN Now() - interval '3 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) +
SUM(CASE WHEN Now() - interval '4 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) +
SUM(CASE WHEN Now() - interval '5 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) +
SUM(CASE WHEN Now() - interval '6 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) +
SUM(CASE WHEN Now() - interval '7 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) +
SUM(CASE WHEN Now() - interval '8 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END)
/ 8) AS available
FROM "parking_meter_transactions"
WHERE
Now() BETWEEN "datetime_start" AND "datetime_stop" OR
Now() - interval '1 week' BETWEEN "datetime_start" AND "datetime_stop" OR
Now() - interval '2 week' BETWEEN "datetime_start" AND "datetime_stop" OR
Now() - interval '3 week' BETWEEN "datetime_start" AND "datetime_stop" OR
Now() - interval '4 week' BETWEEN "datetime_start" AND "datetime_stop" OR
Now() - interval '5 week' BETWEEN "datetime_start" AND "datetime_stop" OR
Now() - interval '6 week' BETWEEN "datetime_start" AND "datetime_stop" OR
Now() - interval '7 week' BETWEEN "datetime_start" AND "datetime_stop" OR
Now() - interval '8 week' BETWEEN "datetime_start" AND "datetime_stop"
GROUP BY "parking_meter_id") AS transactions
基本思路是计算截至now()的“合法”票数,并将其与当天同一时间的最后8周的票数进行比较。这可以给出一个统计概念,即是否应该有一个可用的停车位。
答案 0 :(得分:1)
我建议根据
为您的查询构建覆盖索引( datetime_start, datetime_stop, parking_meter_id )
这样,数据库就不必转到原始数据页面来完成查询。
此外,将WHERE子句调整为单个日期比较范围非常简单。在您的SUM(case)块中,是的,您需要区分它适用于哪个星期,但您的WHERE子句可以简化为类似
WHERE datetime_start > Now() - interval '2 months'
考虑一下......你的#34; NOW()&#34;打电话是不管它是什么......对于笑话,假设1月13日上午12:00。因为所有WHERE子句都是&#34; OR&#34;一起
Now - 2 months = Week of Nov 13
Now - 2 months - 1 week = Week of Nov 20
Now - 2 months - 2 weeks = Week of Nov 27
...
Now - 2 months - 8 weeks = Brings us back to Now...
因此,您的NET时间段是开始日期/时间大于2个月之前的任何时间。
尽管如此,建议的索引应该可以显着提高性能。查看WHERE子句的复杂性,它必须继续计算日期 - 相应的间隔。由于它不能有效地利用索引,因此可能会令人窒息。
在索引中使用仪表ID将有助于GROUP BY子句优化。
每条评论的反馈。
你所有的约会都在FARTHEST,现在() - 2个月。在此之前不要考虑任何事情......但是现在我看到你额外的WHERE条款你如何只想要特定的门票&#34; NOW()&#34;按时计算,为期8周。所以where子句仍然只在单一条件下有效。
让引擎吹过该日期/时间的所有记录,而不应用复杂的WHERE条件。请记住,通过SUM(CASE / WHEN)进行的栏目选择将仅基于那些&#34; Legel&#34;在有关时间内。
SUM(CASE WHEN Now() - interval&#39; 1周&#39; BETWEEN&#34; datetime_start&#34; AND&#34; datetime_stop&#34; THEN 1 ELSE 0 END)+ SUM(现在时间为() - 间隔&#39; 2周&#39; BETWEEN&#34; datetime_start&#34; AND&#34; datetime_stop&#34;那么1 ELSE 0 END)+
所以,如果你正在寻找下午2:53这样的东西,并且你在datetime_start 7:59 pm有一个合格的WHERE子句记录,那么它将失败所有的CASE / WHEN实例和NONE结果列将添加1,从而忽略它们。
因此,即使过去2个月有10k记录,也可以通过索引快速浏览它们。您的案例/何时有资格仅计算您正在寻找的2:53(前:)时间段特定的那些,并且可能仅在所有周期内计算出314个条目。如
Wed, Jan 14 @ 2:53
Wed, Jan 7 @ 2:53
Wed, Dec 31 @ 2:53
Wed, Dec 24 @ 2:53
Wed, Dec 17 @ 2:53
Wed, Dec 10 @ 2:53
Wed, Dec 3 @ 2:53
Wed, Nov 26 @ 2:53
Wed, Nov 19 @ 2:53