PostgreSQL function/query 无限执行

PostgreSQL function/query infinite execution

所以我尝试将我创建的函数用于查询,当我执行查询时它会永远运行。 该函数找到他的订单最大的客户 其中的产品数量。 查询 returns him along with any other 已订购相同数量产品的客户。

函数如下:

CREATE OR REPLACE FUNCTION max_orderQty ()
RETURNS bigint
AS $$
     SELECT SUM(OrderQty)
     FROM Customer,SalesOrderHeader,SalesOrderDetail
     WHERE Customer.CustomerID = SalesOrderHeader.CustomerID
     AND SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
     GROUP BY SalesOrderHeader.CustomerID
     ORDER BY SUM(OrderQty) DESC LIMIT 1;
$$ LANGUAGE SQL;  

这里是查询:

SELECT SUM(OrderQty),SalesOrderHeader.CustomerID
FROM Customer,SalesOrderHeader,SalesOrderDetail
WHERE Customer.CustomerID = SalesOrderHeader.CustomerID
AND SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
GROUP BY SalesOrderHeader.CustomerID
HAVING SUM(OrderQty) = max_orderQty();

这也有效,它解决了同样的问题:(在 220 毫秒内)

SELECT SUM(OrderQty),SalesOrderHeader.CustomerID
FROM Customer,SalesOrderHeader,SalesOrderDetail
WHERE Customer.CustomerID = SalesOrderHeader.CustomerID
AND SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
GROUP BY SalesOrderHeader.CustomerID
HAVING SUM(OrderQty) = (SELECT SUM(OrderQty)
                        FROM Customer,SalesOrderHeader,SalesOrderDetail
                        WHERE Customer.CustomerID = SalesOrderHeader.CustomerID
                        AND SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
                        GROUP BY SalesOrderHeader.CustomerID
                        ORDER BY SUM(OrderQty) DESC LIMIT 1);

所以当我试图将它拆分为 function/query 时,它会永远运行,而我 找不到原因 why.And 我认为使用函数代替 faster.Is 错了吗?

非常感谢任何帮助。 提前致谢。

没有理由认为函数会更快。您的问题是输出中的每一行都调用了该函数——并且每次都重新进行计算。

您应该可以通过将函数声明为 STABLE 来解决此问题;默认值为 VOLATILE.

您可以在 documentation 中阅读这些细微差别。

编辑:

您可以通过仅调用函数一次来强制它 运行 更快:

SELECT SUM(OrderQty),SalesOrderHeader.CustomerID
FROM Customer JOIN
     SalesOrderHeader
     ON Customer.CustomerID = SalesOrderHeader.CustomerID JOIN
     SalesOrderDetail
     ON SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID CROSS JOIN
     (SELECT max_orderQty() as maxoq) x
GROUP BY SalesOrderHeader.CustomerID
HAVING SUM(OrderQty) = MAX(maxoq);