2012-08-02 121 views
1

我正在尝试使用where子句对3个表格进行左连接,并且无法使其工作。在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读取对象时,例如重新打印报告时,我无法获取所有的method_id和描述以显示 - 查询I'已经使用的是:

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. 

任何建议将不胜感激!

回答

2

的问题是左联接返回空值对于在没有找到匹配的行的联接的列值,但要检查的where子句中的列值,但where谓词之后所有行执行加入,所以他们永远不会匹配,你的外部连接被击沉。

即本例中查询:

select * 
from table1 t1 
left join table2 t2 on t2.fk = t1.id 
where t2.col1 = 'x' 

永远返回不具备相应table2行任何行,因为col1null,并与null比较始终false,除了col1 is null

要解决这个问题,就需要测试移动到ON条款,因此比较发生而join正在取得,像这样:

select * 
from table1 t1 
left join table2 t2 on t2.fk = t1.id and t2.col1 = 'x' 

现在左连接仍然会返回行同时在关键字上进行匹配,并应用额外的谓词来进一步优化匹配。


在你的情况,你正在做外(即left)加入到sale_payment p,但where子句,这将无法工作在测试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,因为你没有选择该列,和我添加组m.description,因为你的已经选择了

您可能需要微调查询,但希望这会非常接近

+0

我不知道你可以在ON子句中测试!每天学些新东西! 谢谢! – itsreeyan 2012-08-02 03:05:32