繁体   English   中英

连接三个表并从列数据中减去列的总和

[英]Join three tables and subtract sum of column from a column data

我有三张表accountsreceivablesreceives 。

我的基本表是应收账款我想从账户表中获取名称,然后从具有相同参考号的应收账款表中的应收账款列中减去接收表中收到的列的总和。 如果余额为零,我想忽略。

帐户

ID 姓名
22 约翰
23 卡恩
24 法利斯
25 哈塞尼
26 根特

应收账款

ID 应收款 参考
22 70 A1
24 100 A2
26 60 A3
24 15 A4

收到

参考 ID 已收到
A1 22 30
A2 24 60
A1 22 40
A3 26 20
A2 24 10

期望的结果

ID 姓名 参考 应收款 已收到 平衡 total_id_balance
24 法利斯 A2 100 70 30 45
26 根特 A3 60 20 40 40
24 法利斯 A4 15 0 15 45

我试过这段代码,但它对我不起作用

SELECT * 
FROM receivables AS rvb 
  LEFT JOIN accounts AS acc 
    ON rvb.id = acc.id 
  LEFT JOIN (SELECT SUM(received) as sum_rvd FROM receiveds) AS rvd 
    ON acc.id = rvd.id where rvb.receivable>rvd.sum_rvd

INNER JOIN过滤掉 NULL 值, HAVING子句删除零余额行。


SELECT 
    accounts.* ,
    ra.receivable,
    rd.received,
    ra.receivable - rd.received as balance
FROM accounts
    INNER JOIN ( SELECT id, SUM(receivable) as receivable FROM receivables GROUP BY id ) ra 
        ON ra.id = accounts.id
    INNER JOIN ( SELECT id, SUM(received) as received FROM receiveds GROUP BY id ) rd 
        ON rd.id = accounts.id
HAVING balance > 0

更新

使用ref字段,我们只需要将其添加为子选择的另一个分组字段,并将第二个INNER JOIN更改为LEFT JOIN (实际上看起来从一开始就是一个错误,因为我们错过了没有receiveds但仍然有正余额的条目)。 还将received字段更改为COALESCE以获得零而不是 NULL(表示receiveds表中不存在的行)。 由于您需要一个整体的 per-id total_id_balance字段,因此获取它的自然方法是使用window functions 请注意,它们仅支持 MySQL 8.0+。 因此,生成的查询如下所示:

SELECT 
    accounts.* ,
    ra.ref,
    ra.receivable,
    COALESCE(rd.received, 0) as received,
    ra.receivable - COALESCE(rd.received, 0) as balance,
    SUM( ra.receivable - COALESCE(rd.received, 0) ) OVER ( PARTITION BY id ) as total_id_balance
FROM accounts
    INNER JOIN ( SELECT id, SUM(receivable) as receivable, ref FROM receivables GROUP BY id, ref ) ra 
        ON ra.id = accounts.id
    LEFT JOIN ( SELECT id, SUM(received) as received, ref FROM receiveds GROUP BY id, ref ) rd 
        ON 
            rd.id = accounts.id 
            AND 
            ra.ref = rd.ref
HAVING balance > 0
ORDER BY ref

这对我有用 -

编辑-在receivables中添加对非唯一 ID 的支持

SELECT acc.id ,acc.name, res.receivable, res.received, (res.receivable - res.received) AS balance
FROM accounts AS acc JOIN 
    (SELECT recv.id, recv.receivable, rec.received 
     FROM (
         SELECT id, SUM(receivable) AS receivable
         FROM receivables
         GROUP BY id) AS recv JOIN 
            (SELECT id, SUM(received) AS received 
             FROM receiveds 
             GROUP BY id) AS rec ON rec.id = recv.id 
         WHERE rec.received < recv.receivable) AS res ON res.id = acc.id;

假设在 receivables 中可能有一个 id 而在 receiveds 中没有相应的 id,则第二个连接需要是 LEFT JOIN 并且您需要处理 SELECT 列表中的 NULL -

SELECT 
    a.*,
    ra.receivable,
    IFNULL(rd.received, 0) received,
    ra.receivable - IFNULL(rd.received, 0) balance
FROM accounts a
INNER JOIN (
    SELECT id, SUM(receivable) receivable
    FROM receivables
    GROUP BY id
) ra 
    ON a.id = ra.id
LEFT JOIN (
    SELECT id, SUM(received) received
    FROM receiveds
    GROUP BY id
) rd 
    ON a.id = rd.id
HAVING balance > 0;

您可以(并且应该)更进一步并删除第一个派生表,因为它是不必要的开销 -

SELECT
    a.*,
    SUM(ra.receivable) receivable,
    IFNULL(SUM(rd.received), 0) received,
    SUM(ra.receivable) - IFNULL(rd.received, 0) balance
FROM accounts a
INNER JOIN receivables ra
    ON a.id = ra.id
LEFT JOIN (
    SELECT id, SUM(received) received
    FROM receiveds
    GROUP BY id
) rd
    ON a.id = rd.id
GROUP BY id
HAVING balance > 0;

数据库<>小提琴

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM