sql - 在 sql join 中使用列而不将其添加到 group by 子句

标签 sql postgresql aggregate-functions

我的实际表结构要复杂得多,但以下是两个简化的表定义:

发票

CREATE TABLE invoice (
  id integer NOT NULL,
  create_datetime timestamp with time zone NOT NULL,
  total numeric(22,10) NOT NULL
);

id   create_datetime   total    
----------------------------
100  2014-05-08        1000

payment_invoice

CREATE TABLE payment_invoice (
  invoice_id integer,
  amount numeric(22,10)
);

invoice_id  amount
-------------------
100         100
100         200
100         150

我想通过连接以上 2 个表来选择数据,所选数据应如下所示:-

month      total_invoice_count  outstanding_balance
05/2014    1                    550

我正在使用的查询:

select
to_char(date_trunc('month', i.create_datetime), 'MM/YYYY') as month,
count(i.id) as total_invoice_count,
(sum(i.total) - sum(pi.amount)) as outstanding_balance
from invoice i
join payment_invoice pi on i.id=pi.invoice_id
group by date_trunc('month', i.create_datetime)
order by date_trunc('month', i.create_datetime);

上面的查询给我的结果不正确,因为 sum(i.total) - sum(pi.amount) 返回 (1000 + 1000 + 1000) - (100 + 200 + 150) = 2550
我希望它返回 (1000) - (100 + 200 + 150) = 550

而且我无法将其更改为 i.total - sum(pi.amount),因为这样我就不得不将 i.total 列添加到按子句分组,并且我不想做的事。

最佳答案

您需要每张发票一行,因此请先汇总payment_invoice - 最好在您加入之前。
选择整个表时,通常最快到 aggregate first and join later :

SELECT to_char(date_trunc('month', i.create_datetime), 'MM/YYYY') AS month
     , count(*)                                   AS total_invoice_count
     , (sum(i.total) - COALESCE(sum(pi.paid), 0)) AS outstanding_balance
FROM   invoice i
LEFT   JOIN  (
    SELECT invoice_id AS id, sum(amount) AS paid
    FROM   payment_invoice pi
    GROUP  BY 1
    ) pi USING (id)
GROUP  BY date_trunc('month', i.create_datetime)
ORDER  BY date_trunc('month', i.create_datetime);

LEFT JOIN在这里是必不可少的。您不想丢失在 payment_invoice 中没有对应行的发票(目前),这会发生在普通 JOIN 中。

因此,使用 COALESCE()付款总和,可能为 NULL。

SQL Fiddle改进了测试用例。

关于sql - 在 sql join 中使用列而不将其添加到 group by 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23572238/

相关文章:

javascript - Node.js 将 Postgres SQL 数据加载到 JS 文件中

sql - 获取每天创建的条目数

postgresql - 无法连接到 GCE 虚拟机上的 PostgreSQL 数据库

arrays - 附加到postgres中的多维数组

sql - 左外连接在 Postgres 中深入两层导致笛卡尔积

sql - 使用单个sql命令创建多个表

php - 单个查询中的两个结果

mysql - 如何将3个表与其他表中具有最大值的表组合起来

postgresql - 在 PostgreSQL 中将时间转换为秒

spring - 整合jqgrid、mybatis、spring mvc和postgresql