我有以下查询:
select * from ACADEMIC a
left join RESIDENCY r on a.PEOPLE_CODE_ID = r.PEOPLE_CODE_ID
where a.ACADEMIC_TERM='Fall'
and r.ACADEMIC_TERM='Fall'
and a.ACADEMIC_SESSION=''
and a.ACADEMIC_YEAR = (Select Year(GetDate()))
and r.ACADEMIC_YEAR = (Select Year(GetDate()))
and (CLASS_LEVEL LIKE 'FR%'
OR a.CLASS_LEVEL LIKE 'SO'
OR a.CLASS_LEVEL LIKE 'JR'
OR a.CLASS_LEVEL LIKE 'SR%')
and r.RESIDENT_COMMUTER='R'
对于数据库中的每个人,它返回两行具有相同信息。然而,当我在没有左连接的情况下执行相同的查询时:
select * from ACADEMIC a
where a.ACADEMIC_TERM='Fall'
and a.ACADEMIC_SESSION=''
and a.ACADEMIC_YEAR = (Select Year(GetDate()))
and (CLASS_LEVEL LIKE 'FR%'
OR a.CLASS_LEVEL LIKE 'SO'
OR a.CLASS_LEVEL LIKE 'JR'
OR a.CLASS_LEVEL LIKE 'SR%')
ORDER BY PEOPLE_ID
每个人只返回一行。我正在做一个左连接 - 为什么要添加一个额外的行?如果我添加一个正确的连接,它不应该只这样做吗?
(更新了一致性/可读性的格式。)
答案 0 :(得分:4)
我正在进行左连接 - 为什么要添加额外的行?
您正在进行INNER JOIN
。
这样的条件:
and r.ACADEMIC_TERM='Fall'
有效地过滤掉左连接产生的假行,只留下INNER JOIN
在相同条件下返回的记录。
原因是每个academic
获得两条记录的原因是residency
每academic
有两条记录满足其他连接条件。
如果您希望每residency
只返回一个academic
,则需要定义它是哪一个。
答案 1 :(得分:1)
您获得额外行的原因是您在左连接表的where子句中添加了条件。将r.RESIDENT_COMMUTER ='R'等条件移到join子句中,您将不会遇到这些问题。
例如
select * from ACADEMIC a
left join RESIDENCY r on a.PEOPLE_CODE_ID = r.PEOPLE_CODE_ID
and r.ACADEMIC_YEAR = (Select Year(GetDate()))
and r.RESIDENT_COMMUTER='R'
and r.ACADEMIC_TERM='Fall'
where a.ACADEMIC_TERM='Fall'
and a.ACADEMIC_SESSION=''
and a.ACADEMIC_YEAR = (Select Year(GetDate()))
and (CLASS_LEVEL LIKE 'FR%'
OR a.CLASS_LEVEL LIKE 'SO'
OR a.CLASS_LEVEL LIKE 'JR'
OR a.CLASS_LEVEL LIKE 'SR%')
答案 2 :(得分:1)
您的联接正在从左表中获取符合条件的行,并将它们与右表中的行配对,在每个“a.PEOPLE_CODE_ID = r.PEOPLE_CODE_ID”为真的情况下,将返回此组合。显然,对于每个左手行,这条件满足2行。
答案 3 :(得分:1)
让我们探索两种不同的选择来获得你想要的东西。首先,您需要修复常规查询以将表r上的条件移动到连接。如果您真的需要左连接,请参阅此链接以了解您正在做什么是无关紧要的: http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN
并且不要再在生产代码中使用select *,这是不好的做法。
这是固定查询:
select [List columns here do not list the join column twice!]
from ACADEMIC a
left join RESIDENCY r on a.PEOPLE_CODE_ID = r.PEOPLE_CODE_ID
and r.RESIDENT_COMMUTER='R'
and r.ACADEMIC_TERM='Fall'
and r.ACADEMIC_YEAR = (Select Year(GetDate()))
where a.ACADEMIC_TERM='Fall'
and a.ACADEMIC_SESSION=''
and a.ACADEMIC_YEAR = (Select Year(GetDate()))
and (CLASS_LEVEL LIKE 'FR%'
OR a.CLASS_LEVEL LIKE 'SO'
OR a.CLASS_LEVEL LIKE 'JR'
OR a.CLASS_LEVEL LIKE 'SR%')
如果那样做并不能满足你的需要,那么你可能需要这样做:
select [List columns here for a and r1, do not list the join column twice!]
from ACADEMIC a
left join(select min(people_code_id) from RESIDENCY r on a.PEOPLE_CODE_ID = r.PEOPLE_CODE_ID
and RESIDENT_COMMUTER='R'
and ACADEMIC_TERM='Fall'
and ACADEMIC_YEAR = (Select Year(GetDate())) ) r on a.PEOPLE_CODE_ID = r.PEOPLE_CODE_ID
left join RESIDENCY r1 on r.PEOPLE_CODE_ID = r1.PEOPLE_CODE_ID
where a.ACADEMIC_TERM='Fall'
and a.ACADEMIC_SESSION=''
and a.ACADEMIC_YEAR = (Select Year(GetDate()))
and (CLASS_LEVEL LIKE 'FR%'
OR a.CLASS_LEVEL LIKE 'SO'
OR a.CLASS_LEVEL LIKE 'JR'
OR a.CLASS_LEVEL LIKE 'SR%')
答案 4 :(得分:0)
您的居住表中实际存在什么?什么
SELECT
PEOPLE_CODE_ID,
COUNT(*)
FROM
residency
GROUP BY
PEOPLE_CODE_ID
HAVING
COUNT(*) > 1
给出结果?
LEFT JOIN将为您提供学术表中的所有行,无论您的RESIDENCY表中是否有匹配的行。但是如果您的连接条件在RESIDENCY中有多个匹配的行,那么您仍将获得多行,就像使用INNER JOIN一样。
答案 5 :(得分:0)
不完全确定它为什么会发生,因为我不知道您正在使用的两个表之间的关系(一对多,多对多等)。但是,我可以告诉您,当您在WHERE子句中的“left joined”表中添加一列时,它会取消左连接并使其成为内连接。