将多个SQL查询组合在一起

时间:2012-12-28 19:34:24

标签: mysql

我有一个项目的多个表(会话,收费和付款)

要获得会话,我正在执行以下操作:

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存在于会话中,收费但不支付,我可以在没有会话或费用的情况下付款...

修改:http://sqlfiddle.com/#!2/a90d9

2 个答案:

答案 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值集合的查询的替代品(如上所示)。 scp分别代表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

DEMO HERE