我正在尝试使用 where 子句对 3 个表进行左连接,但无法正常工作。
我的表是:
sale:
sale_id (int)
terminal_id (int)
zread_id (int)
... more fields about total amounts, dates times etc
sale_payment:
payment_id (int)
sale_id (int)
payment_type (enum: 'P','W','A')
method_id (int)
payment_amount (Decimal)
sale_writeoff_method:
method_id (int)
description (varchar)
display_order (int)
销售可以通过 3 种不同的方式(因此是枚举)完成(支付):实物支付 - 现金、支票等,“注销”支付 - 库存以成本价用完(即浪费、赠品等)或账户 - 客户信用等
在销售期结束时(一天结束时),用户执行 Z-Read,收集发生的所有交易并生成报告,然后用户必须在其中平衡抽屉中的现金等。当我'在创建初始 Z-Read 对象时,我可以使用查询收集我需要的信息:
SELECT m.method_id, m.description, SUM(s.sale_total) as z_total, COUNT(s.sale_id) as total_sales
FROM sale_writeoff_method m
LEFT JOIN sale_payment p ON m.method_id = p.method_id
LEFT JOIN sale s ON s.sale_id = p.sale_id
WHERE s.zread_id IS NULL
AND (p.payment_type = 'W' OR p.payment_type IS NULL)
AND (s.terminal_id = ? OR s.terminal_id IS NULL)
GROUP BY p.payment_type, m.method_id
ORDER BY m.display_order;
一旦一切都平衡并最终确定,销售表中所有类型的所有收集的销售都用插入此对象产生的 zread_id 标记。
现在我的问题是,当我将来需要重新创建 z-read 对象时,例如为了重新打印报告,我无法显示所有的 method_id 和描述 - 我的查询一直在使用的是:
SELECT m.method_id, m.description, SUM(s.sale_total) as z_total, COUNT(s.sale_id) as total_sales
FROM sale_writeoff_method m
LEFT JOIN sale_payment p ON m.method_id = p.method_id
LEFT JOIN sale s ON s.sale_id = p.sale_id
WHERE s.zread_id = 1
AND (p.payment_type = 'W' OR p.payment_type IS NULL)
GROUP BY p.payment_type, m.method_id
ORDER BY m.display_order;
But it only displays methods that had sales attached for that Z-Read period. I can't use WHERE s.zread_id IS NULL because that will include all the sales that haven't been finalised yet.
如有任何建议,我们将不胜感激!
最佳答案
问题在于,左联接会为未找到匹配行的联接列值返回空值,但您正在 where
子句中检查这些列值,但 where
谓词在所有行连接后执行,因此它们永远不会匹配并且您的外部连接被沉没。
即这个示例查询:
select *
from table1 t1
left join table2 t2 on t2.fk = t1.id
where t2.col1 = 'x'
永远不会返回在 table2
中没有相应行的任何行,因为 col1
将为 null
,并且与 null
的比较始终为 false
,除了 col1 为 null
。
要解决此问题,您需要将测试移动到 ON
子句中,以便在进行联接时进行比较,如下所示:
select *
from table1 t1
left join table2 t2 on t2.fk = t1.id and t2.col1 = 'x'
现在,左连接在键匹配时仍会返回行,并应用额外的谓词进一步细化匹配。
在您的情况下,您正在执行外部(即 left
)连接到 sale_payment p
,但在 p.payment_type = 'W'
中测试where 子句,这是行不通的。
这是固定查询,在 ON
子句中对左连接表进行了测试:
SELECT
m.method_id,
m.description,
SUM(s.sale_total) as z_total,
COUNT(s.sale_id) as total_sales
FROM sale_writeoff_method m
LEFT JOIN sale_payment p ON m.method_id = p.method_id AND p.payment_type = 'W'
LEFT JOIN sale s ON s.sale_id = p.sale_id AND s.terminal_id = ?
GROUP BY m.method_id, m.description
ORDER BY m.display_order;
请注意,我还删除了 group by p.payment_type
,因为您还没有选择该列,我添加了 group by m.description
,因为您 < em>已经选择了那个。
您可能需要微调查询,但希望这会非常接近
关于mysql - 左连接 3 个表 - 无法正确处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11770182/