计算与约束有关的总和

时间:2014-11-24 16:58:34

标签: sql postgresql aggregate-functions crosstab

我正在使用PostgreSQL 8.4。

我有以下sql-query:

SELECT p.partner_id,
CASE WHEN pa.currency_id = 1 THEN SUM(amount) ELSE 0 END AS curUsdAmount,
CASE WHEN pa.currency_id = 2 THEN SUM(amount) ELSE 0 END AS curRubAmount,
CASE WHEN pa.currency_id = 3 THEN SUM(amount) ELSE 0 END AS curUahAmount
FROM public.player_account AS pa
JOIN player AS p ON p.id = pa.player_id
WHERE p.partner_id IN (819)
GROUP BY p.partner_id, pa.currency_id

问题是查询不符合我的预期。我意识到这一点,但现在我想了解该查询究竟是做什么的。我的意思是,在执行查询后将计算SUM。你能澄清一下吗?

2 个答案:

答案 0 :(得分:2)

我认为你在查询中有条件:

SELECT p.partner_id,
       SUM(CASE WHEN pa.currency_id = 1 THEN amount ELSE 0 END) AS curUsdAmount,
       SUM(CASE WHEN pa.currency_id = 2 THEN amount ELSE 0 END) AS curRubAmount,
       SUM(CASE WHEN pa.currency_id = 3 THEN amount ELSE 0 END) AS curUahAmount
FROM public.player_account pa JOIN
     player p
     ON p.id = pa.player_id
WHERE p.partner_id IN (819)
GROUP BY p.partner_id;

请注意,我还从currency_id子句中删除了group by

答案 1 :(得分:0)

每个(partner_id, currency_id)可能会有一行完成这项工作。这样更快更干净:

SELECT p.partner_id, pa.currency_id, sum(amount) AS sum_amount
FROM   player_account pa
JOIN   player p ON p.id = pa.player_id
WHERE  p.partner_id = 819
AND    pa.currency_id IN (1,2,3)  -- may be redundant if there are not other
GROUP  BY 1, 2;

如果每partner_id需要1行,您实际上在寻找“交叉制表”或“数据透视表”。在Postgres中,使用附加模块crosstab()中的 tablefunc 非常快。 (也可用于过时的版本8.4):

SELECT * FROM crosstab(
   'SELECT p.partner_id, pa.currency_id, sum(amount)
    FROM   player_account pa
    JOIN   player p ON p.id = pa.player_id
    WHERE  p.partner_id = 819
    AND    pa.currency_id IN (1,2,3)
    GROUP  BY 1, 2
    ORDER  BY 1, 2'

   ,VALUES (1), (2), (3)'
   ) AS t (partner_id int, "curUsdAmount" numeric
                         , "curRubAmount" numeric
                         , "curUahAmount" numeric); -- guessing data types

适应您的实际数据类型。

详细说明: