我有相同查询的两个版本,我希望返回相同的结果,但结果是不同的。
查询1:
select * from erp_data.invoices i
left join
(select * from erp_data.invoice_extra_data where data_key = 'job_number') d
using(invoice_id)
where customer_no = '6357' and (data_key = 'job_number' or data_key is null)
and (customer_purchase_order_no ilike '%newtown%' or customer_purchase_order_no ilike '%newtown%' or customer_purchase_order_no ilike '%newton%')
and (order_date >= '2017-09-01' and order_date < '2017-11-01')
查询2:
select * from erp_data.invoices i
left join erp_data.invoice_extra_data d
using(invoice_id)
where customer_no = '6357' and (data_key = 'job_number' or data_key is null)
and (customer_purchase_order_no ilike '%newtown%' or customer_purchase_order_no ilike '%newtown%' or customer_purchase_order_no ilike '%newton%')
and (order_date >= '2017-09-01' and order_date < '2017-11-01')
看起来像postgresql首先进行连接,然后将where cause应用于连接。我这样说是因为发票表中的所有项目都在invoice_extra_data表中有SOMETHING,但并非所有发票都有data_key ='job_number',所以这两个查询会返回不同的结果。
具体而言,第二个查询排除了invoice_extra_data表中没有条目且data_key ='job_number'的发票。可以将预期结果解释为“显示此类发票,因为左连接”或“拒绝此类发票,因为它未通过”where“子句”。
在查询的where部分应用过滤器之前,postgresql是否总是进行连接?
答案 0 :(得分:1)
我这样说是因为发票表中的所有项目都有SOMETHING invoice_extra_data表,但并非所有发票都有 data_key =&#39; job_number&#39;
所以,让我们说你在erp_data.invoice_extra_data where data_key = 'other_id'
中有记录。
在第一个查询中,由于WHERE
语句,在初始左连接期间会排除此记录。然后,您稍后检查该值是否为&#39; job_number&#39;或NULL,因为它被排除,它是NULL。它通过并将被包括在内。
在第二个查询中,在初始左连接期间不会排除此记录,因为它没有WHERE
语句。稍后您会检查该值是否为&#39; job_number&#39;或者NULL,因为它没有被排除,所以它是&#39; other_id&#39;。它现在不会通过,也不会被包括在内。
您的第一个查询,如果您希望简化它,也可以写成:
SELECT *
FROM erp_data.invoices i
LEFT JOIN erp_data.invoice_extra_data d ON i.invoice_id=d.invoice_id
AND data_key = 'job_number'
WHERE customer_no = '6357'
AND (customer_purchase_order_no ilike '%newtown%'
OR customer_purchase_order_no ilike '%newtown%'
OR customer_purchase_order_no ilike '%newton%')
AND order_date >= '2017-09-01'
AND order_date < '2017-11-01'
答案 1 :(得分:0)
问:在应用过滤器之前,postgresql是否总是进行连接 查询的哪个部分?
是的,如The WHERE clause
中所述:
完成FROM子句的处理后,每一行都有 根据搜索条件检查派生的虚拟表。如果 条件的结果为true,该行保存在输出表中, 否则(即,如果结果为假或为空)则将其丢弃。