【发布时间】:2022-08-18 21:42:07
【问题描述】:
我有以下三个表:
-
fees- 包含有关账单费用的信息 -
payments- 包含有关账单支付的信息(包括支付费用) -
details- 有关于付款的详细信息
我很难理解为什么我的查询没有返回我期望的结果。
SQL 小提琴:sqlfiddle.com/#!9/942636/3
CREATE TABLE fees (
receipt_number int(11) NOT NULL,
bill_number int(11) NOT NULL,
version int(11) NOT NULL,
fee_id int(11) NOT NULL,
fee_type varchar(30) NOT NULL
);
CREATE TABLE payments (
receipt_number int(11) NOT NULL,
bill_number int(11) NOT NULL,
version int(11) NOT NULL,
payment_id int(11) NOT NULL,
amount decimal(13,2) NOT NULL DEFAULT \'0.00\'
);
CREATE TABLE details (
receipt_number int(11) NOT NULL,
payment_id int(11) NOT NULL,
fee_type varchar(30) DEFAULT NULL
amount decimal(13,2) NOT NULL DEFAULT \'0.00\'
);
INSERT INTO fees (receipt_number, bill_number, version, fee_id, fee_type)
VALUES (111, 100, 1, 1, \'a\'),
(111, 100, 1, 1, \'b\'),
(111, 100, 1, 2, \'c\'),
(111, 100, 1, 2, \'d\');
INSERT INTO payments (receipt_number, bill_number, version, payment_id, amount)
VALUES (111, 100, 1, 98, 30.00),
(111, 100, 1, 99, 60.00);
INSERT INTO details (receipt_number, payment_id, fee_type, amount)
VALUES (111, 98, \'a\', 10.00),
(111, 98, \'b\', 10.00),
(111, 98, \'d\', 10.00),
(111, 99, \'a\', 20.00),
(111, 99, \'b\', 20.00),
(111, 99, \'c\', 20.00);
我试图找出是否:
- 帐单的费用类型为 \'c\'
- 支付了该费用(由费用类型确定)
我的查询:
SELECT fees.bill_number, details.receipt_number AS has_payment_type_c
FROM fees
LEFT JOIN payments
USING (bill_number, version)
LEFT JOIN details
ON details.receipt_number = payments.receipt_number
AND details.payment_id = payments.payment_id
AND details.fee_type = \'c\'
WHERE fees.fee_type = \'c\'
AND details.receipt_number IS NULL;
我得到结果:
bill_number has_payment_type_c
100 (null)
我应该不是请参阅此列表中的 bill_number,因为该账单有费用和支付该费用的费用。
我正在过滤 ON 子句中的 details.fee_type 以减少在该表中查找的记录数,并仅针对该特定费用类型加入该表。通过将 fee_type 连接条件移动到 WHERE 子句,查询似乎“工作”(0 个结果),但我认为这是不正确的。
我的问题:
- 我在查询中做错了什么?如何修复它以产生我正在寻找的结果,以及该修复如何工作?
- 假设我得到一个有效的查询,我是否可以简单地颠倒表顺序和 SELECT 以找到相反的信息 - 某种费用类型的付款而没有相同类型的相关费用记录?
-
请问1个问题。请使用强制性minimal reproducible example 询问 1 个错误的查询/函数以及为什么您认为它应该在第一个子表达式中返回其他内容,因为它没有给出您期望通过参考权威文档证明的合理性,或者询问您的总体目标提供您可以做的工作部件,最好是minimal reproducible example。但是请先询问前者,因为对前者的误解会妨碍对后者的理解。糟糕的代码不会告诉我们你希望它做什么。
-
很高兴你有点minimal reproducible example。但这应该是您可以提供的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。当你得到一个你不期望的结果时,暂停你的总体目标,切到第一个具有意外结果的子表达式并说出你的期望和原因,并通过文档证明是合理的。 (调试基础。)(否则,您希望我们在您没有完成代码的情况下进行检查,并且您希望我们编写该语言的另一个演示文稿,而不会详细说明您已经误解或做或不做的事情\'不懂。)
-
1. 有什么限制? minimal reproducible example 2. NULL 可以来自任一左连接。未付款的费用将在第一次加入后为空付款,第二次后为空详细信息。 3. 在 AND 和 ON 中都有 details.fee_type = \'c\' 是一个危险信号。 LEFT JOIN 返回由 NULL 扩展的 INNER JOIN 行 UNION ALL 不匹配的左表行。作为 OUTER JOIN 的一部分,始终知道您想要什么 INNER JOIN。
-
将选择更改为选择 *,这样您就可以看到返回的所有内容并从那里开始。
-
这是一个相当不明显的设计。账单有各种版本,每个版本都收取一些费用或一项费用?付款,每笔费用,或其中的一些账单版本的费用?目前尚不清楚系统的状态是什么。您没有为每个基表和您的查询或业务规则或约束提供明确的行成员资格条件(含义)。您对查询如何成为基表或业务情况的功能的描述不清楚且零散。所以我们不知道什么是正确的查询,也不知道什么约束允许进一步的查询表达式是正确的。
标签: mysql left-join filtering where-clause