2015-01-23 2 views
1

이렇게 ... 다소 혼란 스럽습니다. 두 번째 테이블 항목의 목록이 값과 함께, 단지 LEFT OUTER JOIN ... 일치하는 키가 다른 경우

enter image description here

입니다

: 나는 2 개 테이블이 하나의 예를 들면 다음 사람과 주제와 값의 코드 및 이름의 목록은 기본적으로 너무 단순한 숫자 값입니다 "결과"

enter image description here

지금, 내가하고 싶은 것은, 첫 번째 테이블에 LEFT OUTER JOIN을 주제 가치에 일치에서 "결과"필드를 얻을 수 있습니다 두 번째 테이블. 이것은 거의 항상 정확한 일치이기 때문에 대다수의 경우 간단합니다. 그러나 어떤 경우는 존재하지 않을 것입니다. 그런 경우 문제는 표 1의 "값"이 모든 것보다 낮습니다 LEFT OUTER JOIN는 아무 것도 반환하지 않습니다 -이 경우 표 2의 값은, 나는 단순히 1이 강조 표시하려면 테이블에서 해당 주제 2.

가장 낮은 값 을 같게 테이블의 값처럼 가입 할 수 싶습니다 행 2의 경우 주제 30과 함께 표 2에 지리 행이 없기 때문에 주제와 값이 일치합니다.이 경우 값이 35 인 행을 선택하고 결과 필드를 대신 JOIN에 있습니다. 이해

합니까? 그리고 가능한가?

매우 감사드립니다.

+0

을하지만,이 경우 table1''의 값이 모두보다 낮은 'table2'의 값 ... 당신은 무엇을하고 싶습니까? –

+0

@DavidFaber 나는 첫 번째 테이블을 엉망으로 만들었다. 나는 그 포스트를 편집 할 것이고, 혼란에 대해 유감스럽게 생각한다. –

+0

주제가 주제와 비슷합니까? – Strawberry

답변

1

여기에서 교차 적용을 사용할 수 있습니다. 더 나은 솔루션 성능이있을 수 있습니다. 나는 또한 가정하고

declare @people table(
Code int, 
Name varchar(30), 
Topic varchar(30), 
Value int 
) 

declare @topics table(
[Subject] varchar(30), 
Value int, 
Result int 
) 

INSERT INTO @people values (1, 'Doe,John', 'History', 25), 
(2, 'Doe,John', 'Geography', 30), 
(3, 'Doe,John', 'Mathematics', 45), 
(4, 'Doe,John', 'Brad Pitt Studies', 100) 

INSERT INTO @topics values ('History', 25, 95), 
('History', 30, 84), 
('History', 35, 75), 
('Geography', 35, 51), 
('Geography', 40, 84), 
('Geography', 45, 65), 
('Mathematics', 45, 32), 
('Mathematics', 50, 38), 
('Mathematics', 55, 15), 
('Brad Pitt Studies', 100, 92), 
('Brad Pitt Studies', 90, 90) 

SELECT p.Code, p.Name, 
case when p.Value < mTopic.minValue THEN mTopic.minValue 
    else p.Value 
END, mTopic.minValue 
FROM @people p 
CROSS APPLY 
(
SELECT [Subject], 
    MIN(value) as minValue 
FROM @topics t 
WHERE p.Topic = t.Subject 
GROUP BY [Subject] 
) mTopic 

:

이 그들이 거의 항상 그러나 어떤 경우는 없을 것있을 것, 정확히 일치하기 때문에 대부분의 경우에 간단하고,의 이러한 경우 문제는 표 1의 "값"이 표 2의 모든 값보다 낮습니다.

이 맞습니다. Value가 주제 값과 같지 않고 최소값보다 작지 않은 시간이 있으면 '유효한'값이 아니더라도 현재 people.value를 반환합니다 (주제가 유효한 값의 목록이고, 하지만 귀하의 설명에서 알 수 없습니다.)

또한 기술적으로 단지 mTopic.minValue가 아닌 select 문에서 case 문이 필요하지만이 예제가 효과를 더 잘 나타냈다 고 생각했습니다.

+0

안녕하세요 @ david-jacobsen 어리석은 편집에 대한 사과, 분명히 반환 키를 누르지 않아도됩니다. -_-. 어쨌든 ... 정확히 어떻게 작동하는지 혼란 스럽습니다 ... 예와 같이 CASE와 CROSS APPLY가 어떻게 작동합니까? 예를 들어, 표 1의 "Geography"행을 고려한다면 CASE는 CROSS APPLY에 의해 생성 된 "지리"그룹의 최소값? EDIT AGAIN : 신경 쓰지 마라, 나는 바보이다. 고맙습니다. 나는 그것을 시도 할 것입니다. –

+0

Mr @ david-jacobsen, 당신은 신사이고 학자입니다. 그게 내 두뇌를 다치게했지만 완벽하게 작동하는 것 같습니다. 많은 감사합니다. –

+0

나는 그것이 작동하지 않을까 두려워하여 귀하의 의견에 회신하려고했습니다. 내 크롬 탭은 이것이 MySQL이라고 말합니다 - LEFT OUTER JOIN ... 그리고 MySQL이 교차 적용되는 것을 믿지 않습니다! 나는 그것이 당신을 위해 일해서 다행입니다. 짧은 요점은 교차 적용을 사용하면 오른쪽에있는 쿼리 내에서 왼손 테이블의 필드를 사용하여 최소값을 얻을 수 있다는 것입니다. –

0

이 경우에는 하나 대신 두 개의 조인을 만들 것입니다. 다음과 같은 것 :

select * 
from Table1 T1 
LEFT JOIN Table2 T2 on T1.Topic=T2.subject and T1.Value=T2.VALUE 
LEFT JOIN Table2 as T3 on T1.Topic=T3.Subject and T1.Value<T2.Value 

값을 가져올 테이블을 선택하십시오. T2.value가 널이면 T3.Value ELSE T2.Value를 사용하십시오. 희망이 당신을 도울 것입니다

0

또 다른 방법은 임시 테이블을 사용하여 다른 값을 유지하는 것입니다. 먼저 정확한 일치 항목을 삽입 한 다음 초기 선택 항목에없는 일치 항목을 삽입하고 마지막으로 임시 테이블의 모든 결과를 가져옵니다. 이 솔루션은 다른 것보다 더 많은 코드이므로 다른 대안으로 추가하십시오.

예 (SqlFiddle) :

스키마 처음

create table students 
    (code  integer, 
     name  varchar(50), 
     topic varchar(50), 
     value integer); 

create table subjects 
    (subject varchar(50), 
     value varchar(50), 
     result integer); 

insert students 
    (code, name, topic, value) 
values 
    (1, 'Doe, John', 'History',   25), 
    (2, 'Doe, John', 'Geography',   30), 
    (3, 'Doe, Jane', 'Mathematics',  45), 
    (4, 'Doe, Jane', 'Brad Pitt Studies', 100); 

insert subjects 
    (subject, value, result) 
values 
    ('History',   25, 95), 
    ('History',   30, 84), 
    ('History',   35, 75), 
    ('Geography',   35, 51), 
    ('Geography',   40, 84), 
    ('Geography',   45, 65), 
    ('Mathematics',  45, 32), 
    ('Mathematics',  50, 38), 
    ('Mathematics',  55, 15), 
    ('Brad Pitt Studies', 100, 92), 
    ('Brad Pitt Studies', 90, 90); 

실제 SQL 쿼리 :

-- Temp table to hold our results 
create temporary table tempresult 
    (code   integer, 
     name   varchar(50), 
     topic  varchar(50), 
     studentvalue integer, 
     subjectvalue integer, 
     result  integer); 

-- Get the exact results 
insert tempresult 
    (code, 
     name, 
     topic, 
     studentvalue, 
     subjectvalue, 
     result) 
select stu.code, 
     stu.name, 
     stu.topic, 
     stu.value as 'student_value', 
     sub.value as 'subject_value', 
     sub.result 
    from students stu 
     join 
     subjects sub on sub.subject = stu.topic 
        and sub.value = stu.value; 

-- Get the non-exact results, excluding the 'students' that we already 
-- got in the first insert 
insert tempresult 
    (code, 
     name, 
     topic, 
     studentvalue, 
     subjectvalue, 
     result)  
select stu.code, 
     stu.name, 
     stu.topic, 
     stu.value as 'student_value', 
     sub.value as 'subject_value', 
     sub.result 
    from students stu 
     join 
     subjects sub on sub.subject = stu.topic 
         -- Business logic here: Take lowest subject value that is just above the student's value 
        and sub.value = (select min(sub2.value) 
             from subjects sub2 
             where sub2.subject = stu.topic 
             and sub2.value > stu.value) 
where not exists (select 1 
        from tempresult tmp 
        where tmp.code = stu.code 
         and tmp.name = stu.name 
         and tmp.topic = stu.topic) 

-- Get our resultset 
select code, 
     name, 
     topic, 
     studentvalue, 
     subjectvalue, 
     result 
    from tempresult 
order by code, 
      name, 
      topic, 
      studentvalue, 
      subjectvalue, 
      result 
0

왼쪽 된이 요건을 요구하지 조인. T1.Subject = T2.Topic 일 때 참여하고 T1.Value = T2.Value 일 때 또는 T1.Value 일 때 < T2.Value 및 T2.Value가 가장 작은 값입니다.

select p.*, t.Result 
from @People p 
join @Topics t 
    on t.Subject = p.Topic 
    and( t.Value  = p.Value 
     or( p.Value < t.value 
      and t.Value =(
      select Min(Value) 
      from @Topics 
      where Subject = t.Subject))); 

생성 : 그냥 그런 식으로 쓰는 Mathematics``정확히 일치 없다

Code Name  Topic    Value Result 
---- -------- ----------------- ----- ------ 
1 Doe,John History   25 95 
2 Doe,John Geography   30 51 
3 Doe,John Mathematics  45 32 
4 Doe,John Brad Pitt Studies 100 92