2014-10-30 4 views
0

저는 약간의 기본적인 SQL 질문과 도움이 필요하다고 생각합니다. 나는 MSSQL을 사용하고있다.조건부 SQL 조인

나는 두 개의 테이블이 있습니다

 
Table A       Table B 
---------------------------------------------- 
A.ID |A.Date|     B.ID|B.Date|B.Number 

A.ID 고유이다; 중복 된 행이 없습니다. B.ID는 고유하지 않으므로 해당 열의 테이블을 조인하면 여러 행이 반환 될 수 있습니다. 적절한 기록을 잡으려면 두 열 모두에 참여하는 것이 필요하지만 원치 않는 결과도 있습니다. 예 :

 
Table A    |   Table B 
---------------------------------------------- 
1  |01-01-2014  |  1 |01-01-2014|25 
2  |01-30-2014  |  1 |04-30-2013|40 
3  |03-24-2014  |  1 |10-12-2018|12 
4  |05-28-2014  |  2 |11-17-2013|55 

원하는 결과는 두 열을 모두 조인하고 단일 행을 반환하는 것입니다. 내가 실행중인 문제는 샘플 데이터를 사용하여 두 컬럼이 동등한 경우 첫 번째 행만 반환된다는 것입니다. ID 열을 동일하게 설정하고 < =을 사용하면 원하지 않는 ID1에 대해 여러 행이 반환됩니다. 일부 필드에는 두 개의 날짜 필드가 동일해질 때까지 레코드를 반환하지 않아야하는 미래의 날짜가 있기 때문에 최대 날짜를 사용할 수 없습니다. 샘플 데이터에서 원하는 결과는 숫자 25와 55를 반환합니다. 따라서 본질적으로 동일한 ID 열과 같은 날짜 필드에 조인해야하지만 표 B에 동일한 날짜가없는 경우 가장 최근 날짜의 수를 반환합니다. 미래의 날짜가 아니라고 가정합니다.

희망적으로는 의미가 있습니다. 미리 감사드립니다.

+0

그래서 결과는 무엇입니까? 당신에게 맞는 대답을 얻었습니까? – ngreen

+0

나는 거대한 지연에 대해 사과한다. .. 잠깐 길가에 떨어졌다. 결과를 분할하고 원하는 것을 잡기 위해서 ROW OVER와 상관 관계가있는 부질의를 사용했다. – user2820853

답변

0

나는 상관 하위 쿼리 또는 적용 연산자를 사용하는 것이 좋습니다 것입니다.

select a.*, b.* 
from tablea a outer apply 
    (select top 1 b.* 
     from tableb b 
     where b.id = a.id and 
      b.date <= a.date 
     order by b.date desc 
    ) b; 
0

이 시도 :

-- build sample data 
create table #TableA(
    ID int, 
    [Date] smalldatetime 
) 
create table #TableB(
    ID int, 
    [Date] smalldatetime, 
    number int 
) 

insert into #TableA 
select 1, '1/1/2014' union all 
select 2, '1/30/2014' union all 
select 3, '3/24/2014' union all 
select 4, '5/28/2014' 

insert into #TableB 
select 1, '1/1/2014', 25 union all 
select 1, '4/30/2013', 40 union all 
select 1, '10/12/2018', 12 union all 
select 2, '11/17/2013', 55 

-- start 
;with cte(ID, [Date], Number, rn) as(
    select 
     a.id, 
     b.date, 
     number, 
     row_number() over(
      partition by a.id 
      order by 
       case 
        when a.date = b.date then dateadd(d, 1, getdate()) 
        else b.date 
       end 
      desc     
     ) 
    from #TableA a 
    inner join #TableB b 
     on b.id = a.id 
    where 
     a.date <= getdate() 
     and b.date <= getdate() 
) 
select 
    id, 
    date, 
    number 
from cte where rn = 1 
-- end 

-- drop temp tables 
drop table #TableA 
drop table #TableB 
1

그래이 조금 까다 롭습니다하지만 그것을 수행해야합니다 : 여기에 방법입니다 순간에 나에게

with equalvalues as (
select b.* from a 
inner join b on a.ID=b.ID and a.adate=b.bdate 
), 
latestdates as (
select b.id, MAX(b.bdate) as maxbdate 
from b 
where b.bdate<=GETDATE() 
group by b.ID 
) 
select number from equalvalues 
union all 
select b.number from b 
inner join latestdates d on d.ID=b.ID and d.maxbdate=b.bdate 
where b.ID not in (select ID from equalvalues) 
0

내가 사용할 수있는 SQL Server 인스턴스가없는, 그래서 ' PostgreSQL에서 작동하는 구문을 게시하려고합니다. 그것은 꽤 잘 번역되어야합니다. 내 목표는 Table B의 기본 키를 파생시킨 다음 기본 키를 사용하여 행을 선택하는 것이 었습니다. 그것은 당신이 제공 한 샘플 데이터와 함께 작동합니다. 날짜가 너무 먼지 여부를 판단해야하는 규칙이 무엇인지 모르기 때문에 바인딩 변수를 쉽게 바꿀 수있는 하드 코딩 된 날짜를 넣습니다.

with KB as (
    select id as id, max(dt) as dt 
    from (
    select B.id, B.dt, B.num 
    from B 
     inner join A on A.id = B.id and A.dt = B.dt 
    union 
    select B.id, max(B.dt), B.num from B 
     inner join A on A.id = B.id and A.dt != B.dt 
    where B.dt < convert(datetime, '2014.10.313', 102) 
    group by B.id, B.num 
) subquery 
    group by id 
) 
select B.id, B.dt, B.num 
from B 
    inner join KB on KB.id = B.id and X.dt = B.dt; 

작동 방법 : 첫 번째 내부 쿼리 그냥 맹목적으로 정확히 일치를 잡고

. 그들은 필요합니다. 왜 그렇게하지 않습니까? 두 번째 내부 쿼리는 모든 정확하지 않은 일치를 가져옵니다 (ID은 동일하지만 날짜는 아닙니다). equal 집합과 not equal match 집합이 결합되면 외부 쿼리는 각각 ID에 대한 최신 날짜 (max)를 선택합니다. 이 시점에서 모든 행에는 각 ID에 대한 단일 날짜가 필요하므로 남은 유일한 것은 정확히 일치하는 행을 얻는 것입니다.

설명 플랜이 어떻게 보이는지 모르겠습니다. 이 좋지 않아야하지만 완전히 잘못 될 수 있습니다.