0

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

为了获得会议,我正在做以下事情:

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

4

2 回答 2

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值集的查询的替代(如上所示)。、和分别代表 sess、file_charges 和 file_payments 上的三个原始查询scp

如果任何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

(这个查询的解释不会很漂亮,有四个派生表。在非常大的集合上,性能可能很糟糕。但返回的结果集应该符合规范。)

file_id当心将所有三个表连接在一起的查询......当表中有(例如)两个(或更多)行时,可能会给出不正确的结果file_payment

还有其他方法可以获得等效的结果集,但上面的查询回答了这个问题:“我怎样才能将这些查询的结果结合在一起成为一个总数”。


使用相关子查询

这是另一种方法,使用 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
于 2012-12-28T20:56:54.880 回答
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 

编辑。

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

在这里演示

于 2012-12-28T19:45:47.987 回答