我正在尝试使用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种不同方式(因此是Enum)最终确定(支付)实物支付 - 现金,支票等,“注销”支付 - 股票以成本价格用完(即浪费,赠品等)或账户 - 客户信用等
在销售期结束时(一天结束),用户执行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.
任何建议都将不胜感激!
答案 0 :(得分:2)
问题是左连接为没有找到匹配行的连接列值返回空值,但是您正在检查where
子句中的那些列值,但where
谓词是在所有行被连接之后执行,因此它们永远不会匹配,并且您的外连接会被沉没。
即,此示例查询:
select *
from table1 t1
left join table2 t2 on t2.fk = t1.id
where t2.col1 = 'x'
将从不返回table2
中没有相应行的任何行,因为col1
将为null
,并与{{1}进行比较} null
,false
除外。
要解决此问题,您需要将测试移到col1 is null
子句中,以便在进行连接时进行的比较,如下所示:
ON
现在左连接仍会在匹配键时返回行,并应用额外的谓词来进一步细化匹配。
在您的情况下,您正在进行外部(即select *
from table1 t1
left join table2 t2 on t2.fk = t1.id and t2.col1 = 'x'
)加入left
,但在where子句中测试sale_payment p
,这将无效。
这是固定查询,在p.payment_type = 'W'
子句中对左连接表进行测试:
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
分组,因为已选择。
您可能需要微调查询,但希望这将非常接近