左外连接有趣的结果
左外连接有趣的结果
请看下面关于左外连接的两个查询,并告诉我为什么会有差异。
查询1
返回1489行:
SELECT distinct a.GMS_MATERIALNUMBER,a.MATERIAL_DESCRIPTION, b.LDMC FROM [AP_GDC2_PREPARATION_TEST].[dbo].[GDM_AUTOPULL] a left outer join [AP_GDC2_STAGING_TEST].[dbo].[CFS_DIS_LDMC] b on a.GMS_MATERIALNUMBER = b. GMS_MATERIALNUMBER and b.SAP_COMPANY_CODE= '1715' and a.CFS_ORGANIZATION_CODE like 'rd_kr'
查询2
只返回295行,这与我执行简单的select * from a where CFS_ORGANIZATION_CODE like 'rd_kr'得到的行数相同。
SELECT distinct a.GMS_MATERIALNUMBER,a.MATERIAL_DESCRIPTION, b.LDMC FROM [AP_GDC2_PREPARATION_TEST].[dbo].[GDM_AUTOPULL] a left outer join [AP_GDC2_STAGING_TEST].[dbo].[CFS_DIS_LDMC] b on a.GMS_MATERIALNUMBER = b. GMS_MATERIALNUMBER and b.SAP_COMPANY_CODE= '1715' where a.CFS_ORGANIZATION_CODE like 'rd_kr'
基本上,查询2
是我想要的结果,但我的问题是为什么查询1
不起作用?在处理left outer join
的ON
子句时,SQL服务器在后台是如何工作的呢?
谢谢。
左外连接(LEFT JOIN)和内连接(JOIN)的区别导致了这样的结果。使用左外连接(LEFT JOIN)时,会返回第一个表的所有行以及与第二个表匹配的行。而在第二个查询中,先进行了内连接(JOIN),然后在设置了WHERE语句来减少结果。
要解决这个问题,可以通过以下方法之一来改变查询的顺序:
1. 将表的顺序交换。如果你想要的结果是左外连接(LEFT JOIN)的结果,可以将第一个表和第二个表的顺序交换。这样,第一个表将成为LEFT JOIN的左表,而第二个表将成为LEFT JOIN的右表。
2. 将内连接(JOIN)的查询结果作为子查询。你可以将内连接(JOIN)的查询结果作为一个子查询,然后在外部查询中使用LEFT JOIN。这样,你可以先得到内连接的结果,然后再通过LEFT JOIN获取所有第一个表的行。
下面是两种解决方法的示例代码:
方法1:交换表的顺序
SELECT *
FROM table2
LEFT JOIN table1 ON table2.id = table1.id
方法2:使用子查询
SELECT *
FROM (
SELECT *
FROM table1
JOIN table2 ON table1.id = table2.id
) AS subquery
LEFT JOIN table2 ON subquery.id = table2.id
通过使用这些解决方法,你就可以得到期望的LEFT JOIN的有趣结果了。
在上面的内容中,我们可以看到问题的原因是第一个查询在连接表之前对表进行了过滤,而第二个查询在连接表之后对结果进行了过滤。这导致了两个查询结果的差异。
解决方法是在第一个查询中,将过滤条件移动到连接条件的后面,以确保在连接表之后进行过滤。这样可以得到与第二个查询相同的结果。
具体来说,我们可以将第一个查询改写为:
SELECT a.*, b.Score FROM Table1 a LEFT JOIN Table2 b ON a.ID = b.T1_ID WHERE b.Score >= 20
这样修改后的查询将会得到与第二个查询相同的结果:
ID Name Score 2 Over 20 3 Flow 30