[英]combining multiple sql queries together
我有一个项目的多个表(会话,费用和付款)
为了获得会议,我正在做以下事情:
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)
请注意,它可能为负数,因此我可以拥有存在于session中的file_id,收费但不存在于付款中,并且我可以没有会话或收费地进行付款...
需要解决的一个问题是,在我们没有由一个或多个查询返回的给定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不会很漂亮,有四个派生表。在非常大的集合上,性能可能令人恐怖。但是返回的结果集应符合规范。)
当心将所有三个表联接在一起的查询...如果file_payment
表中的同一个file_id
有(例如)两(或更多)行,则可能会给出错误的结果。
还有其他方法可以得到等效的结果集,但是上面的查询回答了以下问题:“如何将这些查询的结果汇总在一起”。
使用相关子查询
这是另一种方法,在SELECT列表中使用相关子查询...
SELECT a.file_id
, IFNULL( ( SELECT SUM(file_payments.paymentAmount) FROM file_payments
WHERE file_payments.file_id = a.file_id )
,0)
- ( IFNULL( ( SELECT SUM(sess.rate * sess.length) FROM sess
WHERE sess.file_id = a.file_id )
,0)
+ IFNULL( ( SELECT SUM(file_charges.price) FROM file_charges
WHERE file_charges.file_id = a.file_id )
,0)
) AS tot
FROM ( -- all file_id values
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
ORDER BY a.file_id
尝试这个
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
编辑。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.