【发布时间】:2012-02-02 10:29:53
【问题描述】:
我有两个 MySQL 表,结构如下(我已经删除了不相关的列)。
mysql> DESCRIBE `edinners_details`;
+------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+----------------+
| details_id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| details_pupil_id | int(11) unsigned | NO | | NULL | |
| details_cost | double unsigned | NO | | NULL | |
+------------------+------------------+------+-----+---------+----------------+
mysql> DESCRIBE `edinners_payments`;
+------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+----------------+
| payment_id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| payment_pupil_id | int(11) unsigned | NO | | NULL | |
| payment_amount | float unsigned | NO | | NULL | |
+------------------+------------------+------+-----+---------+----------------+
系统的工作方式是您点餐,每餐都有费用,这些订单中的每一个都存储在edinners_details。示例行如下:
mysql> SELECT * FROM `edinners_details` LIMIT 1;
+------------+------------------+--------------+
| details_id | details_pupil_id | details_cost |
+------------+------------------+--------------+
| 1 | 18343 | 25 |
+------------+------------------+--------------+
通常,人们会批量支付这些餐费 - 如果他们在 20 天内有价值 40 英镑的餐费,他们将在月底付清。每次付款时,edinners_payments 表中都会有一个新行,示例行如下:
mysql> SELECT * FROM `edinners_payments` LIMIT 1;
+------------+------------------+----------------+
| payment_id | payment_pupil_id | payment_amount |
+------------+------------------+----------------+
| 1 | 18343 | 20 |
+------------+------------------+----------------+
因此,从这两行中,我们可以看到此人目前欠债 5 英镑 - 他们吃了 25 英镑的饭菜,只付了 20 英镑。随着时间的推移,系统的每个用户都会有很多行,我可以通过一个简单的查询来轻松计算出他们有多少食物价值,例如
SELECT SUM(`details_cost`) AS `meal_total`
FROM `edinners_details`
WHERE `details_pupil_id` = '18343';
然后要获得他们支付的金额,我只需进行以下查询:
SELECT SUM(`payment_amount`) AS `payment_total`
FROM `edinners_payments`
WHERE `payment_pupil_id` = '18343';
我的最终目标是能够查看谁欠的钱最多,但是循环我的users 表的每个用户并为他们运行这两个查询,我相信这会很慢,所以理想情况下我会喜欢做的是将上述两个查询合并为一个,也许还有一个附加列,即 (meal_total - payment_total),它会给我所欠的金额。我已经尝试了一些方法来完成这项工作,包括连接和子查询,但它们似乎都重复了 edinners_details 中每个 edinners_payments 行中的每个相关行 - 所以如果有 3 个详细信息和 4 个付款,您将拉出 12 行,这意味着对列执行 SUM() 会给我一个远远超过应有的值。证明这一点的一个好方法是运行这个查询:
SELECT * FROM (
SELECT `details_cost` AS `cost`
FROM `edinners_details`
WHERE `details_pupil_id` = '18343'
GROUP BY `details_id`
) AS `details`, (
SELECT `payment_amount` AS `amount`
FROM `edinners_payments`
WHERE `payment_pupil_id` = '18343'
GROUP BY `payment_id`
) AS `payment`;
这给了我以下结果:
+------+--------+
| cost | amount |
+------+--------+
| 2.5 | 20 |
| 2.5 | 6 |
| 2.5 | 3 |
| 2.5 | 1200 |
| 2.5 | 20 |
| 2.5 | 6 |
| 2.5 | 3 |
| 2.5 | 1200 |
| 2.5 | 20 |
| 2.5 | 6 |
| 2.5 | 3 |
| 2.5 | 1200 |
| 2.5 | 20 |
| 2.5 | 6 |
| 2.5 | 3 |
| 2.5 | 1200 |
| 2.5 | 20 |
| 2.5 | 6 |
| 2.5 | 3 |
| 2.5 | 1200 |
+------+--------+
将 SUM 添加到其中,如下所示:
SELECT SUM(`details`.`cost`) AS `details_cost`, SUM(`payment`.`amount`) AS `payment_total` FROM (
SELECT `details_cost` AS `cost`
FROM `edinners_details`
WHERE `details_pupil_id` = '18343'
GROUP BY `details_id`
) AS `details`, (
SELECT `payment_amount` AS `amount`
FROM `edinners_payments`
WHERE `payment_pupil_id` = '18343'
GROUP BY `payment_id`
) AS `payment`;
给我以下结果:
+--------------+---------------+
| details_cost | payment_total |
+--------------+---------------+
| 50 | 6145 |
+--------------+---------------+
如果这有效,details_cost 将是 12.5,payment_total 将是 1229,但事实并非如此。您可以清楚地看到上述结果中的重复,我很抱歉所有费用都是 2.5,这让它不太明显,但它们是 5 份单独的餐点订单,已经支付了 4 次付款。有谁知道我将如何同时获得订餐费用的 SUM() 和付款的 SUM()?
谢谢
【问题讨论】: