Postgresql查询放置的位置会导致不同的结果

时间:2017-11-01 14:28:09

标签: postgresql

我有相同查询的两个版本,我希望返回相同的结果,但结果是不同的。

查询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是否总是进行连接?

2 个答案:

答案 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,该行保存在输出表中,   否则(即,如果结果为假或为空)则将其丢弃。