INNER JOIN 改变 SUM 结果

Posted

技术标签:

【中文标题】INNER JOIN 改变 SUM 结果【英文标题】:INNER JOIN change SUM result 【发布时间】:2021-01-14 18:32:03 【问题描述】:
CREATE TABLE beauty.customer_payments
(
customer_id integer,
date date,
amount numeric(10,2),
CONSTRAINT customer_payments_customer_id_fkey FOREIGN KEY    (customer_id)
    REFERENCES beauty.customers (customer_id) MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
)
CREATE TABLE beauty.sales
(
product_id integer,
customer_id integer,
sell_date date NOT NULL,
qty integer NOT NULL,
sell_price numeric(10,2) NOT NULL,
expiry_date date NOT NULL,
CONSTRAINT sales_customer_id_fkey FOREIGN KEY (customer_id)
    REFERENCES beauty.customers (customer_id) MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION,
CONSTRAINT sales_product_id_fkey FOREIGN KEY (product_id)
    REFERENCES beauty.products (product_id) MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
)

customer_id=6 的付款余额 beauty.customer_payments 为 0

 SELECT * FROM beauty.customer_payments 
 WHERE customer_id=6;
customer_id date amount
6 2020-11-14 75.00
6 2020-11-14 -75.00
 SELECT * FROM beauty.sales 
 WHERE customer_id=6;
product_id customer_id sell_date qty sell_price expiry_date
76 6 2020-11-14 1 75.00 2022-03-03
83 6 2020-11-14 1 10.00 2022-06-23
85 6 2020-11-14 1 10.00 2022-06-23
44 6 2020-11-14 1 12.00 2022-06-23
41 6 2020-11-14 1 15.00 2022-03-26
96 6 2020-11-14 1 75.00 2022-03-15
28 6 2020-11-14 1 4.00 2022-01-22
33 6 2020-11-14 1 4.00 2023-01-23
37 6 2020-11-14 1 4.00 2023-01-23
40 6 2020-11-14 1 4.00 2023-08-13

(10 行)

SELECT customer_id, SUM(qty * sell_price) AS purchased
FROM beauty.sales
WHERE customer_id=6
GROUP BY customer_id;
customer_id purchased
6 213.00
SELECT s.customer_id, 
SUM(qty * sell_price) AS purchased, 
SUM(cp.amount) AS paid,
SUM(qty * sell_price - cp.amount) AS balance
FROM beauty.sales s
INNER JOIN beauty.customer_payments cp 
ON cp.customer_id = s.customer_id
WHERE s.customer_id=6 
GROUP BY s.customer_id;
customer_id purchased paid balance
6 1065.00 0.00 1065.00

请告知为什么添加JOIN (INNER, LEFT, RIGHT)后计算出错以及如何解决这个多重计算问题? 正如我看到的类似问题,所有这些问题都基于非交叉表计算,如SUM(qty * sell_price - cp.amount)

删除付款

`
DELETE FROM beauty.customer_payments
WHERE customer_id=6;`

添加新的零支付

INSERT INTO beauty.customer_payments(
customer_id, date, amount)
VALUES (6, '2020-11-17', 0);
customer_id purchased paid balance
6 213.00 0.00 213.00

添加付款 10

INSERT INTO beauty.customer_payments(
customer_id, date, amount)
VALUES (6, '2020-11-17', 10);

SELECT * FROM beauty.customer_payments WHERE customer_id=6;
customer_id date amount
6 2020-11-17 0.00
6 2020-11-17 10.00
SELECT s.customer_id, 
.......
INNER JOIN beauty.customer_payments cp 
.......
customer_id purchased paid balance
6 426.00 100.00 326.00

正确支付负数

INSERT INTO beauty.customer_payments(
customer_id, date, amount)
VALUES (6, '2020-11-17', -10);
SELECT * FROM beauty.customer_payments WHERE customer_id=6;
customer_id date amount
6 2020-11-17 0.00
6 2020-11-17 10.00
6 2020-11-17 -10.00
SELECT s.customer_id, 
.......
INNER JOIN beauty.customer_payments cp 
.......
customer_id purchased paid balance
6 639.00 0.00 639.00

这个 `INNER JOIN' 计算的是什么?

【问题讨论】:

“beauty.customer_payments 中没有记录”,但 inner join 查询返回该记录?这似乎是不可能的。 请查看更改...意味着customer_id=6没有记录 【参考方案1】:

通常,您可能不希望将每笔付款与每笔销售相匹配(除非有一个额外的标识符将特定付款与特定销售相匹配,而不仅仅是将每笔付款与客户相匹配)。

如果客户有 10 美元和 15 美元的 2 笔销售,以及 9 美元和 14 美元的两次付款,则您的加入会将每笔付款与该客户的每笔销售相匹配,从而创建类似

Sale Payment
$10 $9
$10 $14
$15 $9
$15 $14

因此,加入后的总销售额将为 50 美元,而不是 25 美元(如您所料)。我认为以上回答了您关于为什么加入没有达到您期望的问题。

您想要的确切查询可能会有所不同(您是否希望所有客户即使没有销售?如果客户没有销售,他们是否可以付款?),但总的来说我' d期望类似以下的工作。有多种方法可以做到这一点,但我认为以下方法很容易理解,因为它在加入之前将数据聚合到每个客户一个付款行和每个客户一个销售行。

SELECT
 s.customer_id,
 s.purchased,
 cp.amount as paid,
 s.purchased - cp.amount as balance
FROM
 (SELECT s.customer_id, 
 SUM(s.qty * s.sell_price) AS purchased
 FROM beauty.sales s 
 GROUP BY s.customer_id) s
LEFT OUTER JOIN
 (SELECT cp.customer_id, 
 SUM(cp.amount) AS amount
 FROM beauty.customer_payments cp 
 GROUP BY cp.customer_id) cp
ON s.customer_id = cp.customer_id
WHERE s.customer_id = 6

【讨论】:

非常感谢这个详细的解释为什么它的计算与不同的销售和付款条目以及代码不同。我工作得很好。

以上是关于INNER JOIN 改变 SUM 结果的主要内容,如果未能解决你的问题,请参考以下文章

来自第二个表的 MySQL INNER JOIN (TOP10)

SQL中inner join,outer join和cross join的区别

展平 SQL 服务器 INNER JOIN 结果 [重复]

使用 INNER JOIN 排除 MYSQL 查询结果

在网页上将 INNER JOIN 结果显示为 HTML 表格?

Inner Join, Left Outer Join和Association的区别