mysql - 左连接 3 个表 - 无法正确处理

标签 mysql

我正在尝试使用 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/

相关文章:

mysql - 使用 Min(field) 的问题

python - 从 MySQL 将数字数据加载到 python/pandas/numpy 数组的最快方法

MySQL插入错误1064

php - 当我使用 mysqli 点击提交时执行多重查询

php - 数据表js和查询数php mysql

php - 将新数据添加到表的自动化过程

php - 在 MySQL 中使用 LIMIT 根据列值限制结果 (PHP/MySQL)

mysql - mysql中如何对不同子表求和?

Javascript console.log 端口

Java MySQL 连接器无法使用 JOIN 子句正确返回表行