postgresql - PostgreSQL。存储函数或查询改进
问题描述
我正在使用PostgreSQL并且有一个员工表:
employeeid | FirstName | LastName | Department | Position
1 | Aaaa | | |
2 | Bbbb | | |
3 | | | |
. | | | |
报告表:
employeeid | enter | exit
1 | 2020-11-08 09:02:21 | 2020-11-08 18:12:01
. | ... |
现在,我正在查询某个日期错过的员工,类似于该功能:
for i in select employeeid from employee
loop
if select not exists(select 1 from reports where enter::date = '2020-11-08' and employeeid = i) then
return query select employeeid, lastname, firstname, department, position from employee where employeeid = i;
end if;
end loop;
在我看来,这不是一个理想的解决方案。有没有更好的方法来达到相同的结果?谢谢。
解决方案
您的代码非常无效。可能它不能写得不好:-)。回复@a_horse_with_no_name 是绝对正确的,只是为了完整起见,我将修复您的 plpgsql 代码。
DECLARE _e employee;
BEGIN
FOR _e IN SELECT * FROM employee
LOOP
IF NOT EXISTS(SELECT *
FROM reports r
WHERE r.enter::date = date '2020-11-08'
AND r.employeeid = _e.employeeid)
THEN
RETURN NEXT _e;
END IF;
END LOOP;
END;
当您编写存储过程(或任何基于查询的应用程序)时,重要的值是查询的数量 - 数量越少越好(注意 - 有例外 - 有时过于复杂的查询可能会因为它们的复杂性而变慢)。在您的示例中,有employees * 2 + 1
查询(plpgsql 的开销更大 -RETURN QUERY
比 更昂贵RETURN NEXT
)。@a_horse_with_no_name 提出的解决方案是一个查询(没有 plpgsql 的开销)。我的任何示例都有employees + 1
查询(plpgsql 的开销较低)。
您的示例是一种常见 SQL 反模式的好示例 - “使用 ISAM 样式”。