左连接未按预期拉出空值
我有一个看起来像这样的查询(我已经更改了表名称):
select @user_id
, isnull(ur.rule_value, isnull(manr.rule_value, def.rule_value)) [rule_value]
, isnull(urt.name, isnull(manrt.name, def.name)) [rule_type]
from (select @user_id [user_id]
, rule.rule_value
, rule_type.name
from rule
join rule_type on rule_type.rule_type_id = rule.rule_type_id
where rule.user_id = 1) def
join user on user.user_id = def.user_id
join manager man on man.manager_id = user.manager_id
left join rule ur on ur.user_id = user.user_id
left join rule_type urt on urt.rule_type_id = ur.rule_type_id
left join rule manr on manr.manager_id = man.manager_id
left join rule_type manrt on manrt.rule_type_id = manr.rule_type_id
我期望的是,当没有针对用户或用户经理的规则时,则应使用默认规则。但是,只有当用户有规则时我才会得到结果。
我已经尝试过左连接所有内容,但没有成功,并且 def
表的 select 语句返回了所有默认规则。
我做错了什么?
@user_id
是一个变量。
更新
架构示例
rule
rule_id user_id manager_id rule_value
1 1 1 27
2 1 1 24
3 1 1 25
4 1 1 44
5 1 1 88
1 2 4 2
2 2 4 23
3 2 4 18
3 NULL 4 19
4 NULL 4 20
5 NULL 4 21
rule_type
rule_id name
1 'Craziness'
2 'Number of legs'
3 'Hair ranking'
4 'Banana preference'
5 'Rule 5'
user
user_id manager_id ... other columns
1 1
2 4
3 4
manager
manager_id ... other columns
1
2
3
4
5
6
因此,如果 @user_id
是 2
那么我期望输出
2, 2, 'Craziness'
2, 23, 'Number of legs'
2, 18, 'Hair ranking'
2, 20, 'Banana preference'
2, 21, 'Rule 5'
但是如果 @user_id 是 < code>3 那么我期望输出
3, 27, 'Craziness'
3, 24, 'Number of legs'
3, 19, 'Hair ranking'
3, 20, 'Banana preference'
3, 21, 'Rule 5'
I have a query that looks something like this (I've changed the table names):
select @user_id
, isnull(ur.rule_value, isnull(manr.rule_value, def.rule_value)) [rule_value]
, isnull(urt.name, isnull(manrt.name, def.name)) [rule_type]
from (select @user_id [user_id]
, rule.rule_value
, rule_type.name
from rule
join rule_type on rule_type.rule_type_id = rule.rule_type_id
where rule.user_id = 1) def
join user on user.user_id = def.user_id
join manager man on man.manager_id = user.manager_id
left join rule ur on ur.user_id = user.user_id
left join rule_type urt on urt.rule_type_id = ur.rule_type_id
left join rule manr on manr.manager_id = man.manager_id
left join rule_type manrt on manrt.rule_type_id = manr.rule_type_id
What I'm expecting is that when there isn't a rule for the user or the user's manager, then the default rule should be used. However, I'm only getting a result if the user has a rule.
I've tried left join
ing everything but to no avail, and the select statement for the def
table brings back all the default rules.
What am I doing wrong?
@user_id
is a variable.
Update
Example of schema
rule
rule_id user_id manager_id rule_value
1 1 1 27
2 1 1 24
3 1 1 25
4 1 1 44
5 1 1 88
1 2 4 2
2 2 4 23
3 2 4 18
3 NULL 4 19
4 NULL 4 20
5 NULL 4 21
rule_type
rule_id name
1 'Craziness'
2 'Number of legs'
3 'Hair ranking'
4 'Banana preference'
5 'Rule 5'
user
user_id manager_id ... other columns
1 1
2 4
3 4
manager
manager_id ... other columns
1
2
3
4
5
6
So if @user_id
is 2
then I would expect the output
2, 2, 'Craziness'
2, 23, 'Number of legs'
2, 18, 'Hair ranking'
2, 20, 'Banana preference'
2, 21, 'Rule 5'
But if @user_id is 3
then I would expect the output
3, 27, 'Craziness'
3, 24, 'Number of legs'
3, 19, 'Hair ranking'
3, 20, 'Banana preference'
3, 21, 'Rule 5'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
常规连接实际上是左内连接。您真正想要的是一个外部联接,它可以获取结果,即使它无法将其与另一个表联接。
A regular join is actually a left inner join. What you actually want is an outer join, which fetches the result, even if it cannot join it with the other table.
要回答标题中的问题,左连接的作用与常规连接不同。 LEFT JOIN 与 LEFT OUTER JOIN 相同,意味着也会返回 LEFT 表中不符合 ON 条件的记录。
To answer the question in the title, a LEFT JOIN does NOT act like a REGULAR JOIN. The LEFT JOIN is the same as the LEFT OUTER JOIN, meaning will also return the records in the LEFT table that don't match the ON criteria.
摆脱这个 :
并用这个 : 替换它,
然后将你的开始 SELECT 更改为 :
本质上你做错的是你有一个实体(用户经理默认)并且你试图将它链接到另一个实体(规则)通过两个不同的连接。如果一个联接不起作用,但另一个联接起作用,则不会返回匹配的 NULL 供 ISNULL 查找。这有点违反直觉。
Get rid of this :
and replace it with this :
then change your opening SELECT to :
Essentially what you're doing wrong is that you have one entity (user-manager-default) and you're trying to link it to a different entity (rule) via two different joins. If one join doesn't work but the other does, there's no matching NULL returned for your ISNULL to find. It's a little counter-intuitive.
我已将查询分为两部分。
我认为因为表结构比我在原始问题中提出的更复杂,这意味着 CodeByMoonlight 的答案还不够 - 它给了我无法解释的重复行。
我的解决方案如下(关于我在问题中给出的细节):
I've split the query into two parts.
I think because the table structures are more complicated than I put into the original question, this means that CodeByMoonlight's answer isn't quite enough - it was giving me duplicate rows that I couldn't account for.
My solution is as follows (with respect to the details I gave in the question):