Php 从两个不同的表中获取两列的总和
我有两个MySQL表,结构如下(我删除了不相关的列) 该系统的工作方式是,您点一顿饭,每顿饭都有成本,每一份订单都存储在Php 从两个不同的表中获取两列的总和,php,mysql,math,sum,Php,Mysql,Math,Sum,我有两个MySQL表,结构如下(我删除了不相关的列) 该系统的工作方式是,您点一顿饭,每顿饭都有成本,每一份订单都存储在edinners\u details中。示例行如下所示: mysql> SELECT * FROM `edinners_details` LIMIT 1; +------------+------------------+--------------+ | details_id | details_pupil_id | details_cost | +----------
edinners\u details
中。示例行如下所示:
mysql> SELECT * FROM `edinners_details` LIMIT 1;
+------------+------------------+--------------+
| details_id | details_pupil_id | details_cost |
+------------+------------------+--------------+
| 1 | 18343 | 25 |
+------------+------------------+--------------+
mysql> SELECT * FROM `edinners_payments` LIMIT 1;
+------------+------------------+----------------+
| payment_id | payment_pupil_id | payment_amount |
+------------+------------------+----------------+
| 1 | 18343 | 20 |
+------------+------------------+----------------+
通常情况下,人们会批量支付这些餐费——如果他们在20天内有价值40英镑的餐费,他们会在月底付清。每次他们付款时,都会有一个新行进入edinners\u payments
表,示例行如下:
mysql> SELECT * FROM `edinners_details` LIMIT 1;
+------------+------------------+--------------+
| details_id | details_pupil_id | details_cost |
+------------+------------------+--------------+
| 1 | 18343 | 25 |
+------------+------------------+--------------+
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';
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`;
我的最终目标是能够看到谁欠的钱最多,但是要循环我的users
表中的每个用户并为他们运行这两个查询,我相信这会非常慢,所以理想情况下,我想做的是将上面两个查询合并成一个查询,也许还需要一个额外的列(餐费总额
-付款总额
)我尝试了一些方法来实现这一点,包括联接和子查询,但它们似乎都重复了edinners\u details
中每个edinners\u付款
行中的每一行相关内容-因此,如果有3个细节和4个付款,则将有12行被拉出,这意味着要执行列上的SUM()为我提供了一个远远超过其应有值的值。运行此查询是证明这一点的一个好方法:
SELECT SUM(`payment_amount`) AS `payment_total`
FROM `edinners_payments`
WHERE `payment_pupil_id` = '18343';
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 |
+------+--------+
+--------------+---------------+
| details_cost | payment_total |
+--------------+---------------+
| 50 | 6145 |
+--------------+---------------+
将总和加在其中,如下所示:
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`;
给我以下结果:
+------+--------+
| 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 |
+------+--------+
+--------------+---------------+
| details_cost | payment_total |
+--------------+---------------+
| 50 | 6145 |
+--------------+---------------+
如果这是可行的,细节成本
将是12.5,付款总额
将是1229,但事实并非如此。你可以清楚地看到上述结果中的重复,我很抱歉,所有成本都是2.5,这让它变得不那么明显,但它们是5份单独的餐单,已经支付了4笔款项。有人知道吗你知道我该如何同时得到点餐费用和付款总额吗
感谢当前,您的查询正在执行一个交叉连接,它将第一个表中的每一行连接到第二个表中的每一行,因此返回大量冗余结果。但是,两个表都有一个
瞳孔id
,因此我们可以使用它来连接每个表中的正确记录
SELECT
d.detail_pupil_id AS pupil_id,
SUM(d.details_cost) AS cost,
SUM(p.payment_amount) AS amount
FROM `edinners_details` d
INNER JOIN `edinners_payments` p ON d.detail_pupil_id = p.payment_pupil_id
GROUP BY pupil_id;
您可以通过执行到users
表的联接,并在一个查询中返回所需的所有数据来进一步实现这一点
SELECT
users.id,
users.name,
payment.cost,
payment.amount
FROM `users`
INNER JOIN (
SELECT
d.detail_pupil_id AS pupil_id,
SUM(d.details_cost) AS cost,
SUM(p.payment_amount) AS amount
FROM `edinners_details` d
INNER JOIN `edinners_payments` p ON d.detail_pupil_id = p.payment_pupil_id
GROUP BY pupil_id
) payment ON payment.pupil_id = users.id
ORDER BY users.id ASC;
我手头只有PostgreSQL可用,这就是我想到的:
SELECT coalesce(costs.pupil_id, amounts.pupil_id) as pupil_id,
coalesce(amount_sum, 0) as amount_sum,
coalesce(cost_sum, 0) as cost_sum,
coalesce(amount_sum, 0) - coalesce(cost_sum, 0) as debit
FROM (
SELECT details_pupil_id AS pupil_id,
sum(details_cost) AS cost_sum
FROM edinners_details
GROUP BY details_pupil_id
) costs
FULL OUTER JOIN
(
SELECT payment_pupil_id AS pupil_id,
sum(payment_amount) AS amount_sum
FROM edinners_payments
GROUP BY payment_pupil_id
) amounts ON costs.pupil_id = amounts.pupil_id;
它是按学生id对每个表中的记录进行分组,以正确计算总数,然后将它们合并以获得差额。当有人没有任何付款(但有晚餐)或没有任何晚餐(但有付款)时,可以使用完全外部联接来处理这种情况
据我所知,MySQL不支持完全外部连接(bump…),因此您必须使用UNION来模拟它:
SELECT coalesce(costs.pupil_id, amounts.pupil_id) AS pupil_id,
coalesce(amount_sum, 0) as amount_sum,
coalesce(cost_sum, 0) as cost_sum,
coalesce(amount_sum, 0) - coalesce(cost_sum, 0) AS debit
FROM (
SELECT details_pupil_id AS pupil_id,
sum(details_cost) AS cost_sum
FROM edinners_details
GROUP BY details_pupil_id
) costs
LEFT OUTER JOIN
(
SELECT payment_pupil_id AS pupil_id,
sum(payment_amount) AS amount_sum
FROM edinners_payments
GROUP BY payment_pupil_id
) amounts ON costs.pupil_id = amounts.pupil_id
UNION
SELECT coalesce(costs.pupil_id, amounts.pupil_id) AS pupil_id,
coalesce(amount_sum, 0) as amount_sum,
coalesce(cost_sum, 0) as cost_sum,
coalesce(amount_sum, 0) - coalesce(cost_sum, 0) AS debit
FROM (
SELECT details_pupil_id AS pupil_id,
sum(details_cost) AS cost_sum
FROM edinners_details
GROUP BY details_pupil_id
) costs
RIGHT OUTER JOIN
(
SELECT payment_pupil_id AS pupil_id,
sum(payment_amount) AS amount_sum
FROM edinners_payments
GROUP BY payment_pupil_id
) amounts ON costs.pupil_id = amounts.pupil_id;
以下内容适合我,尽管看起来很难看。在MySQL数据库中:
SELECT
t1.p_id, t1.cost, t2.amount
FROM
(SELECT
details_pupil_id AS p_id, SUM(details_cost) AS cost
FROM
edinners_details
GROUP BY
details_pupil_id) t1,
(SELECT
payment_pupil_id AS p_id, SUM(payment_amount) AS amount
FROM
edinners_payments
GROUP BY
payments_pupil_id) t2
WHERE
t1.p_id = t2.p_id
/* Getting pupils with dinners but no payment */
UNION
SELECT
details_pupil_id, SUM(details_cost) cost, 0
FROM
edinners_details
WHERE
details_pupil_id NOT IN (SELECT DISTINCT payment_pupil_id FROM edinners_payments)
GROUP BY
details_pupil_id
/* Getting pupils with payment but no dinners */
UNION
SELECT
payment_pupil_id, 0, SUM(payment_amount)
FROM
edinners_payments
WHERE
payment_pupil_id NOT IN (SELECT DISTINCT details_pupil_id FROM edinners_details)
GROUP BY
payment_pupil_id
你可以尝试以下类似的方法,它应该返回你债务最大的学生的借记和支付金额(如果一个学生多付了他的债务将是负数): 因此,如果您有以下情况:
mysql> select * from edinners_details;
+------------+------------------+--------------+
| details_id | details_pupil_id | details_cost |
+------------+------------------+--------------+
| 1 | 18343 | 25 |
| 2 | 18344 | 17 |
| 3 | 18343 | 11 |
| 4 | 18344 | 2 |
| 5 | 18344 | 7 |
| 6 | 18343 | 12 |
| 7 | 18343 | 12 |
| 8 | 18343 | 35 |
| 9 | 18344 | 30 |
+------------+------------------+--------------+
mysql> select * from edinners_payments;
+------------+------------------+----------------+
| payment_id | payment_pupil_id | payment_amount |
+------------+------------------+----------------+
| 1 | 18343 | 20 |
| 2 | 18344 | 25 |
| 3 | 18343 | 12 |
| 4 | 18344 | 25 |
| 5 | 18343 | 22 |
| 6 | 18344 | 11 |
| 7 | 18343 | 8 |
| 8 | 18344 | 2 |
+------------+------------------+----------------+
运行上述查询时,您应该得到:
+-------+--------------+
| id | max(t.debit) |
+-------+--------------+
| 18343 | 33 |
+-------+--------------+
如果您想要每个学生的借项列表,您可以运行:
select details_pupil_id as id, (sum(details_cost) - (select sum(payment_amount) from edinners_payments where payment_pupil_id = details_pupil_id)) as debit from edinners_details group by details_pupil_id;
这将使您获得以下结果:
+-------+-------+
| id | debit |
+-------+-------+
| 18343 | 33 |
| 18344 | -7 |
+-------+-------+
我希望这能有所帮助。你好,Gary,谢谢你的回复,我已经将你提供的第一个查询直接运行到我的测试表上,但我似乎仍然遇到同样的问题-表1中的每一行都连接到表2中的每一行。令人烦恼的是,我没有空间在这个评论中粘贴查询结果,但它非常相似回复到原始帖子中的那个。有什么想法吗?谢谢。我建议使用上面Furgas的答案。我已经对一个测试数据库运行了他的查询,它返回了您要查找的结果:。祝您好运!感谢您链接到SQLFiddle,我以前没有看到过它,它将来可能会有用。谢谢您的帮助。您将不会看到SQLFiddle没有任何付款(但有晚餐),学生没有晚餐(但有付款)。您好,非常感谢您,这正是我要找的。我稍微修改了它,将债务计算添加到其中,只检索负债的人,这给我留下了。再次感谢。(还有:为什么我的新行不在这里工作?我在做双空格…)你好,Furgas,谢谢你的回复。出于某种原因,你的查询结果与@e.alhajri的查询结果非常不同。我将对我拥有的数据进行手动清点,看看哪一个是正确的。再次感谢。啊,不,我错了;只是正/负相反。你的数据确实给了我正确的数据,谢谢你的帮助。遗憾的是,我不能给两个人打上正确的标记,也不能给他们报应,但请放心,如果我可以的话,我会的。