MySQL比较WHERE子句中的结果

时间:2016-04-11 23:51:43

标签: mysql

我想我在这里错过了一些非常明显的东西。

我正在尝试显示“预订”列表,其中总费用高于预订的总付款。费用和付款存储在使用外键链接的单独表格中。

到目前为止,我的查询是:

SELECT `booking`.`id`,
SUM(`booking_charge`.`amount`) AS `charges`,
SUM(`booking_payment`.`amount`) AS `payments`

FROM `booking`
LEFT JOIN `booking_charge` ON `booking`.`id` = `booking_charge`.`booking_id`
LEFT JOIN `booking_payment` ON `booking`.`id` = `booking_payment`.`booking_id`

WHERE `charges` > `payments` ///this is the incorrect part

GROUP BY `booking`.`id`

我的表格如下所示:

Booking (ID)

Booking_Charge (Booking_ID, Amount)

Booking_Payment (Booking_ID, Amount)

MySQL似乎不喜欢比较这两个表的结果,我不确定我缺少什么,但我确信这是可能的。

2 个答案:

答案 0 :(得分:1)

尝试HAVING代替WHERE,就像这样

SELECT `booking`.`id`,
SUM(`booking_charge`.`amount`) AS `charges`,
SUM(`booking_payment`.`amount`) AS `payments`
FROM `booking`
LEFT JOIN `booking_charge` ON `booking`.`id` = `booking_charge`.`booking_id`
LEFT JOIN `booking_payment` ON `booking`.`id` = `booking_payment`.`booking_id`
GROUP BY `booking`.`id`
HAVING `charges` > `payments`

答案 1 :(得分:1)

One of the problems with the query is the cross join between rows from `_charge` and rows from `_payment`. It's a semi-Cartesian join. Each row returned from `_charge` will be matched with each row returned from `_payment`, for a given `booking_id`.

Consider a simple example:

Let's put a single row in `_charge` for $40 for a particular `booking_id`.

And put two rows into `_payment` for $20 each, for the same `booking_id`.

The query will would return total charges of $80. (= 2 x $40). If there were instead five rows in \'_payment\' for $10 each, the query would return a total charges of $200 ( = 5 x $40)

There's a couple of approaches to addressing that issue. One approach is to do the aggregation in an inline view, and return the total of the charges and payments as a single row for each booking_id, and then join those to the booking table. With at most one row per booking_id, the cross join doesn't give rise to the problem of "duplicating" rows from _charge and/or _payment.

For example:

  SELECT b.id
       , IFNULL(c.amt,0)  AS charges
       , IFNULL(p.amt,0)  AS payments
    FROM booking b
    LEFT
    JOIN ( SELECT bc.booking_id
                , SUM(bc.amount) AS amt
             FROM booking_charge bc
            GROUP BY bc.booking_id
         ) c
      ON c.booking_id = b.id
    LEFT
    JOIN ( SELECT bp.booking_id
                , SUM(bp.amount) AS amt
             FROM booking_payment bp
            GROUP BY bp.booking_id
         ) p
      ON p.booking_id = b.id
   WHERE IFNULL(c.amt,0) > IFNULL(p.amt,0)

We could make use of a HAVING clause, in place of the WHERE.


The query in this answer is not the only way to get the result, nor is it the most efficient. There are other query patterns that will return an equivalent result.