sql - 在 Postgresql 中实现类似 FOR 循环的功能

标签 sql postgresql for-loop

我已经接触数据库几年了,我开始能够很好地处理大多数 SQL/Postgresql 查询,但我仍然不明白应该如何在其中完成一个简单的类似 FOR 的查询.这是一个伪代码示例:

FOR id IN SELECT ids FROM parents WHERE name ilike '%something%' LOOP
    SELECT parent_id, max(timestamp) FROM children WHERE parent_id = id;
END LOOP;

注意:一位 parent 可以有并且经常有多个 child ,因此他们之间存在一对多关系。

该查询的预期结果应该是这样的:

parent_id, max(timestamp)
5, 2015-09-18 10:00:46.684824+03
6, 2015-09-18 10:00:47.684824+03
8, 2015-09-18 10:00:48.684824+03
etc.

查询本身不必是 for 循环。我只是对如何用 SQL 表达这个查询感兴趣,因为我似乎经常需要它。

谢谢!

最佳答案

有几种方法,有些比其他的好。

总的来说,我提倡在使用 SQL 和关系数据库时学习集合 思考。当您将 JOIN 视为对集合的操作时,它们开始变得很有意义。 WHEREGROUP BY 等过滤器也是如此。您经常会发现您可以开始用英语表达您的查询,并在一段时间后将它们“翻译”成 SQL。 (或者也许我只是写了太多的 SQL,现在我已经损坏了)。

带分组和聚合的连接

在我看来,使用连接和 GROUP BY 是最清晰和最简单的表达方式。你说“这是这两个表之间的关系,现在为每个 p.ids 得到 max(c.timestamp)”。

SELECT
   p.ids,
   max(c.timestamp)
FROM parents
  LEFT OUTER JOIN children c ON (p.ids = c.parent_id)
WHERE p.name ILIKE '%something%'
GROUP BY p.ids;

我使用了 LEFT OUTER JOIN,因为在简单的 FOR 循环中,您会得到一个带有 parent_id 和 null max 的结果如果没有匹配的行。这保留了相同的行为。如果在没有子行的情况下根本不想要任何行,请使用 inner join

相关子查询

SELECT
   p.ids,
   (SELECT max(timestamp) FROM children c WHERE c.parent_id = p.ids)
FROM parents
WHERE p.name ILIKE '%something%';

这种方法仅限于您只需要关联子表中的一个字段的情况,除非您开始使用复合记录做一些可怕的事情。它通常会产生与连接方法相同的查询计划,但灵 active 较低。

它更接近于“for 循环”方法,因为它说“对每个父行在子表上执行此操作”。

PL/PgSQL 中的FOR 循环

这是最慢且笨拙的,但几乎就是您所写的内容。

FOR id IN SELECT ids FROM parents WHERE name ilike '%something%' LOOP
    RETURN QUERY SELECT parent_id, max(timestamp) FROM children WHERE parent_id = id;
END LOOP;

是的,我几乎一字不差地复制了您的代码。它看起来像完全有效的 PL/PgSQL,只是没有结果的目的地。在上面的表格中,您需要声明过程 RETURNS TABLE(...)

最后一个是 PL/PgSQL,所以它只在函数中有效。

它最接近你写的东西,在程序上思考时也是最简单的,但实际上又慢又麻烦。

关于sql - 在 Postgresql 中实现类似 FOR 循环的功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32646580/

相关文章:

postgresql - NiFi ifelse 表达式不能按预期使用 bool 值

sql - 根据所选列中的相同值向行添加数字

python - 为什么我的列表在我尝试 append 它们时没有加入 Python

JavaScript:如何将 for/of 循环转换为带变量的普通 for 循环?

php - 获取所有以字符串开头的表名

sql - 使用存储过程借方贷方

postgresql - postgres,go-gorm-无法预加载数据

c - 运行时错误 - SIGSEGV

mysql - 如何改进存储过程查询

sql - 从 T-SQL 中的字符串中提取最大数字