[英]Join three tables and subtract sum of column from a column data
我有三张表accounts , receivables和receives 。
我的基本表是应收账款我想从账户表中获取名称,然后从具有相同参考号的应收账款表中的应收账款列中减去接收表中收到的列的总和。 如果余额为零,我想忽略。
帐户
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.