2009-12-14 2 views
0

나는 이런 식으로 뭔가를 보이는 쿼리가 예상 널 (null)를 잡아 당겨하지 조인 :왼쪽 (I 테이블 이름을 변경 한)

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 테이블에 대한 select 문은 모든 기본 규칙을 다시 가져옵니다.

내가 뭘 잘못하고 있니?

@user_id은 변수입니다.

업데이트

@user_id2 경우 스키마의 예

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 

그럼 내가 기대하는 출력

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' 

답변

1

저는 두 부분으로 쿼리를 분할했습니다.

테이블 구조가 원래 질문에 넣는 것보다 복잡하기 때문에 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 
1

정규 결합은 실제로 왼쪽 내부 결합입니다. 실제로 원하는 것은 외부 조인입니다. 외부 조인은 다른 테이블과 조인 할 수 없더라도 결과를 가져옵니다.

1

제목에있는 질문에 대답하기 위해 LEFT JOIN은 규칙적인 결합처럼 작동하지 않습니다. LEFT JOIN은 LEFT OUTER JOIN과 동일합니다. 즉, LEFT 테이블에서 ON 기준과 일치하지 않는 레코드도 반환합니다. 이 그것을

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 

및 교체 :

+0

왜 내 쿼리가 일어나는되지 않습니다 :

내 솔루션 (I 질문에 준 세부 사항에 관하여) 다음과 같다? –

+0

내부 선택은 실제로 규칙이있는 userId 만 반환합니다. 규칙이없는 사용자를 반환하려면 "rule.user_id = 1 또는 rule.user_id가 NULL 인 위치"라고 말하고 싶을 수 있습니다. – tzup

+0

def 테이블을 생성하는 쿼리는 올바른 행 번호를 제공합니다. 나는 여분의 절이 어떻게 도움이 될지 모르겠다. –

1

이 제거하십시오 당신이 잘못하고있는 것을 본질적으로

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

:

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 

다음을 선택하여 열기를 변경 하나의 엔티티 (user-manager-default)가 있고 두 엔티티를 통해 다른 엔티티 (룰)에 연결하려고한다는 것입니다 fferent 조인. 한 조인이 작동하지 않지만 다른 조인이 작동하는 경우 ISNULL에서 찾은 일치하는 NULL이 리턴되지 않습니다. 반 직관적입니다.

+0

+1 내 최종 답변에 나를 잡았습니다. –

관련 문제