[英]Getting the sum of two columns from two different tables
我有兩個具有以下結構的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_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
,則details_cost
為12.5, payment_total
為1229,但實際情況並非如此。 您可以清楚地看到上述結果中的重復,對不起,所有費用均為2.5,這使費用降低了一些,但它們是5份單獨的餐點,已支付4筆款項。 有誰知道我要如何同時獲取餐單成本的SUM()和付款的SUM()?
謝謝
我手頭只有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不支持FULL OUTER JOIN(凸點...),因此您必須使用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;
當前,您的查詢正在執行CROSS JOIN
,它將第一張表中的每一行連接到第二張表中的每一行,因此返回了大量冗余結果。 但是,兩個表都有一個pupil_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;
以下內容對我有用,盡管看上去很丑。 在MySQL DB中:
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
您可以嘗試以下類似的方法,該方法應向您退還負債最大的學生的借方和身份證(如果學生多付了其債務,則為負):
select t.id, max(t.debit) from (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) as t;
因此,如果您有以下情況:
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 |
+-------+-------+
我希望這有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.