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

私が期待しているのは、ユーザーまたはユーザーのマネージャーのルールがない場合は、デフォルトのルールを使用する必要があるということです。ただし、ユーザーにルールがある場合にのみ結果が得られます。

私はleft joinすべてを試みましたが、役に立たず、defテーブルの選択ステートメントはすべてのデフォルトルールを取り戻します。

私は何を間違っていますか?

@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の場合3、出力が期待されます

3, 27, 'Craziness'
3, 24, 'Number of legs'
3, 19, 'Hair ranking'
3, 20, 'Banana preference'
3, 21, 'Rule 5'
4

4 に答える 4

1

通常の結合は、実際には左内部結合です。実際に必要なのは、他のテーブルと結合できない場合でも、結果をフェッチする外部結合です。

于 2009-12-14T12:29:32.757 に答える
1

タイトルの質問に答えると、LEFT JOIN は REGULAR JOIN のようには機能しません。LEFT JOIN は LEFT OUTER JOIN と同じです。つまり、ON 条件に一致しない LEFT テーブルのレコードも返されます。

于 2009-12-14T12:30:29.727 に答える
1

これを取り除きます:

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]

基本的に間違っているのは、1 つのエンティティ (user-manager-default) があり、2 つの異なる結合を介して別のエンティティ (ルール) にリンクしようとしていることです。1 つの結合が機能せず、もう 1 つの結合が機能する場合、ISNULL が検索する一致する NULL が返されません。少し直感に反します。

于 2009-12-14T13:16:17.747 に答える
1

クエリを 2 つの部分に分割しました。

テーブル構造は元の質問よりも複雑であるため、これは 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
于 2009-12-14T15:05:36.093 に答える