左连接未按预期拉出空值

发布于 2024-08-14 04:41:19 字数 2052 浏览 7 评论 0原文

我有一个看起来像这样的查询(我已经更改了表名称):

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_id2 那么我期望输出

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 joining 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

卸妝后依然美 2024-08-21 04:41:19

常规连接实际上是左内连接。您真正想要的是一个外部联接,它可以获取结果,即使它无法将其与另一个表联接。

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.

把时间冻结 2024-08-21 04:41:19

要回答标题中的问题,左连接的作用与常规连接不同。 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.

鹿! 2024-08-21 04:41:19

摆脱这个 :

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

并用这个 : 替换它,

left join rule ur on ur.user_id = user.user_id or ur.user_id = man.manager_id
left join rule_type urt on urt.rule_type_id = ur.rule_type_id

然后将你的开始 SELECT 更改为 :

select @user_id
,      isnull(ur.rule_value, def.rule_value) [rule_value]
,      isnull(urt.name, def.name) [rule_type]

本质上你做错的是你有一个实体(用户经理默认)并且你试图将它链接到另一个实体(规则)通过两个不同的连接。如果一个联接不起作用,但另一个联接起作用,则不会返回匹配的 NULL 供 ISNULL 查找。这有点违反直觉。

Get rid of this :

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

and replace it with this :

left join rule ur on ur.user_id = user.user_id or ur.user_id = man.manager_id
left join rule_type urt on urt.rule_type_id = ur.rule_type_id

then change your opening SELECT to :

select @user_id
,      isnull(ur.rule_value, def.rule_value) [rule_value]
,      isnull(urt.name, def.name) [rule_type]

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.

雪花飘飘的天空 2024-08-21 04:41:19

我已将查询分为两部分。

我认为因为表结构比我在原始问题中提出的更复杂,这意味着 CodeByMoonlight 的答案还不够 - 它给了我无法解释的重复行。

我的解决方案如下(关于我在问题中给出的细节):

create table #user_rules
(
 user_id int,
 rule_value int,
 rule_type varchar(255),
 rule_type_id,
)
--Insert default values
insert into #user_rules
select @user_id [user_id]
    , rule.rule_value
    , rule_type.name
    , rule_type.rule_type_id
from rule
join rule_type on rule_type.rule_type_id = rule.rule_type_id
where rule.user_id = 1
--Update table with any available values
update #user_rules
set rule_value = ur.rule_value
from user u
join manager m on u.manager_id = m.manager_id
join rule ur on ur.user_id = u.user_id or (ur.manager_id = man.manager_id and ur.user_id is null)
join rule_type urt on urt.rule_type_id = ur.rule_type_id
where urt.rule_type_id = #urse_rules.rule_type_id
and u.user_id = @user_id

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):

create table #user_rules
(
 user_id int,
 rule_value int,
 rule_type varchar(255),
 rule_type_id,
)
--Insert default values
insert into #user_rules
select @user_id [user_id]
    , rule.rule_value
    , rule_type.name
    , rule_type.rule_type_id
from rule
join rule_type on rule_type.rule_type_id = rule.rule_type_id
where rule.user_id = 1
--Update table with any available values
update #user_rules
set rule_value = ur.rule_value
from user u
join manager m on u.manager_id = m.manager_id
join rule ur on ur.user_id = u.user_id or (ur.manager_id = man.manager_id and ur.user_id is null)
join rule_type urt on urt.rule_type_id = ur.rule_type_id
where urt.rule_type_id = #urse_rules.rule_type_id
and u.user_id = @user_id
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文