SELECT
business_period,
SUM(transaction.transaction_value) AS total_transaction_value,
SUM(transaction.loss_value) AS total_loss_value,
(total_transaction_value - total_loss_value) AS net_value
FROM transaction
GROUP BY business_period
上述内容不起作为total_transaction_value
,而total_loss_value
不在transaction
表中。有没有办法让这个查询有效?
注意:此查询涉及5亿行,因此需要高效。
问题:
一些答案表明SUM(transaction.transaction_value) - SUM(transaction.loss_value)
被缓存,并且不需要再次计算,而其他人则建议我应该作为派生表/子查询来避免重复计算。有人能指出可以解决意见分歧的事情吗?
我正在使用postgres 9.3。
解答:
我想在这里引用erwin的评论:
I ran a quick test with 40k rows and the winner was the plain version without subquery. CTE was slowest. So I think my first assumption was wrong and the query planner understands not to calculate the sums repeatedly (makes sense, too). I have seen different results with more complex expressions in the past. The planner does get smarter with every new version
答案 0 :(得分:1)
使用:
SELECT
business_period,
SUM(transaction.transaction_value) AS total_transaction_value,
SUM(transaction.loss_value) AS total_loss_value,
(SUM(transaction.transaction_value) - SUM(transaction.loss_value)) AS net_value
FROM transaction
GROUP BY business_period
答案 1 :(得分:0)
再次使用sum
SELECT
business_period,
SUM(transaction.transaction_value) AS total_transaction_value,
SUM(transaction.loss_value) AS total_loss_value,
(SUM(transaction.transaction_value) - SUM(transaction.loss_value)) AS net_value
FROM transaction
GROUP BY business_period
答案 2 :(得分:0)
只需明确重申SUM(我相信它们只计算一次):
SELECT
business_period,
SUM(transaction.transaction_value) AS total_transaction_value,
SUM(transaction.loss_value) AS total_loss_value,
SUM(transaction.transaction_value) - SUM(transaction.loss_value) AS net_value
FROM transaction
GROUP BY business_period
或者你可以使用派生表子查询,如果上面没有隐式地执行它,它应该强制它只计算一次 - 尽管可能会有一些额外的开销,具体取决于优化器看到的内容:
SELECT business_period,
total_transaction_value,
total_loss_value,
(total_transaction_value - total_loss_value) AS net_value
FROM
(
SELECT
business_period,
SUM(transaction.transaction_value) AS total_transaction_value,
SUM(transaction.loss_value) AS total_loss_value,
FROM transaction
GROUP BY business_period
) x
答案 3 :(得分:0)
使用子查询以避免重复计算:
SELECT *, total_transaction_value - total_loss_value AS net_value
FROM (
SELECT business_period
, SUM(transaction_value) AS total_transaction_value
, SUM(loss_value) AS total_loss_value
FROM transaction
GROUP BY 1
) sub;
或CTE (common table expresson)实际强制这一点,因为CTE构成优化障碍。对于像这样的简单情况,子查询通常更快。当折叠子查询更快时,Postgres会更清楚。