我有一个项目的多个表(会话,收费和付款)
要获得会话,我正在执行以下操作:
SELECT
sess.file_id, SUM(sess.rate * sess.length) AS total
FROM
sess
WHERE sess.sessionDone = 1
GROUP BY sess.file_id
这将返回特定学生应支付的金额
我还有另一张桌子“收费”
SELECT
file_charges.file_id, SUM(file_charges.price) AS total_charges
FROM
file_charges
GROUP BY file_charges.file_id
最后付款查询:
SELECT
file_payments.file_id, SUM(file_payments.paymentAmount) AS total_payment
FROM
file_payments
GROUP BY file_payments.file_id
我可以将这些3组合起来:
Total = Payments - (Session + Charges)
请注意,它可能是否定的,所以我可以将file_id存在于会话中,收费但不支付,我可以在没有会话或费用的情况下付款...
答案 0 :(得分:3)
需要解决的一个问题是,如果我们没有一个或多个查询返回的给定file_id
的行,这些查询中的一个是否可以是“驱动程序”。 (例如,sess
可能有行,但file_payments
可能没有行。如果我们想确保包含任何查询中出现的每个可能的file_id
,我们就可以获得一个列表所有可能file_id
的查询都是这样的:
SELECT ss.file_id FROM sess ss
UNION
SELECT fc.file_id FROM file_charges fc
UNION
SELECT fp.file_id FROM file_payments fp
(注意:UNION运算符将删除任何重复项)
要获取指定的结果集,我们可以使用该查询以及其他三个原始查询的“左连接”。查询的大纲将是:
SELECT a.file_id, p.total_payment - ( s.total + c.total_charges)
FROM a
LEFT JOIN s ON s.file_id = a.file_id
LEFT JOIN c ON c.file_id = a.file_id
LEFT JOIN p ON p.file_id = a.file_id
ORDER BY a.file_id
在该语句中a
是获取所有file_id
值集合的查询的替代品(如上所示)。 s
,c
和p
分别代表sess,file_charges和file_payments三个原始查询。
如果任何查询中的任何file_id
值“丢失”,我们将需要用零替换缺失值。我们可以使用IFNULL函数为我们处理。
此查询应返回指定的结果集:
SELECT a.file_id
, IFNULL(p.total_payment,0) - ( IFNULL(s.total,0) + IFNULL(c.total_charges,0)) AS t
FROM ( -- all possible values of file_id
SELECT ss.file_id FROM sess ss
UNION
SELECT fc.file_id FROM file_charges fc
UNION
SELECT fp.file_id FROM file_payments fp
) a
LEFT
JOIN ( -- the amount that a specific student should pay
SELECT sess.file_id, SUM(sess.rate * sess.length) AS total
FROM sess
WHERE sess.sessionDone = 1
GROUP BY sess.file_id
) s
ON s.file_id = a.file_id
LEFT
JOIN ( -- charges
SELECT file_charges.file_id, SUM(file_charges.price) AS total_charges
FROM file_charges
GROUP BY file_charges.file_id
) c
ON c.file_id = a.file_id
LEFT
JOIN ( -- payments
SELECT file_payments.file_id, SUM(file_payments.paymentAmount) AS total_payment
FROM file_payments
GROUP BY file_payments.file_id
) p
ON p.file_id = a.file_id
ORDER BY a.file_id
(此查询的EXPLAIN不会很漂亮,有四个派生表。在非常大的集合上,性能可能很糟糕。但返回的结果集应符合规范。)
请注意将所有三个表连接在一起的查询...如果({1}}表中有相同file_id
的(例如)两行(或更多行),则可能会给出错误的结果
还有其他方法可以获得等效的结果集,但上面的查询回答了这样一个问题:“我怎样才能将这些查询的结果连接在一起”。
使用相关子查询
这是另一种方法,在SELECT列表中使用相关子查询...
file_payment
答案 1 :(得分:1)
试试这个
SELECT sess.file_id, SUM(file_payments.paymentAmount) - (SUM(sess.rate * sess.length)+SUM(file_charges.price)) as total_payment FROM sess , file_charges , file_payments
WHERE sess.sessionDone = 1
GROUP BY total_payment
EDIT。
SELECT a.file_id
, IFNULL(p.total_payment,0) - ( IFNULL(s.total,0) + IFNULL(c.total_charges,0)) AS tot
FROM (
SELECT ss.file_id FROM sess ss
UNION
SELECT fc.file_id FROM file_charges fc
UNION
SELECT fp.file_id FROM file_payments fp
) a
LEFT JOIN (
SELECT sess.file_id, SUM(sess.rate * sess.length) AS total
FROM sess
WHERE sess.sessionDone = 1
GROUP BY sess.file_id
) s
ON s.file_id = a.file_id
LEFT JOIN (
SELECT file_charges.file_id, SUM(file_charges.price) AS total_charges
FROM file_charges
GROUP BY file_charges.file_id
) c
ON c.file_id = a.file_id
LEFT JOIN (
SELECT file_payments.file_id, SUM(file_payments.paymentAmount) AS total_payment
FROM file_payments
GROUP BY file_payments.file_id
) p
ON p.file_id = a.file_id
ORDER BY a.file_id