繁体   English   中英

结合多个SQL查询在一起

[英]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,收费但不存在于付款中,并且我可以没有会话或收费地进行付款...

编辑: http : //sqlfiddle.com/#!2/a90d9

需要解决的一个问题是,在我们没有由一个或多个查询返回的给定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不会很漂亮,有四个派生表。在非常大的集合上,性能可能令人恐怖。但是返回的结果集应符合规范。)

当心将所有三个表联接在一起的查询...如果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.

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