2012-04-17 4 views
5

두 테이블을 결합하려고하지만 이상한 요구 사항이 있습니다. 레코드가 그 고객에 대한하며 코드 그러나복잡한 SQL 조인

SELECT * 
    FROM DataTable d 
    JOIN LookupTable l 
     ON d.LookupCode = l.LookupCode 
     AND d.Customer = l.Customer 

, 내가 뭘해야 룩업 테이블에서 세 행에 조인을 일치합니다

은 일반적으로 그냥 결합 할 것입니다. 일치하는 ID와 다른 열 (순서)의 정렬 순서에 따라 앞뒤 행 (존재하는 경우). 그런 다음 결과를 정렬해야합니다. 먼저 일치하는 레코드와 이전의 조회 레코드를 비교 한 다음 일치 레코드 뒤에있는 조회 레코드를 정렬해야합니다.

이 작업을 수행하는 가장 좋은 방법에 대한 의견이 있으십니까?

예 :

Lookup: 
Customer Code Order 
12345 A  1 
12345 B  2 
12345 C  3 
12345 D  4 
12345 E  5 
22222 A  1 
22222 B  2 
22222 D  4 
22222 E  5 

Data: 
Customer Code 
12345  B 
12345  D 
22222  B 
22222  D 

Result I need 
Customer Code 
12345  B 
12345  A 
12345  C 
12345  D 
12345  C 
12345  E 
22222  B 
22222  A 
22222  D 
22222  D 
22222  B 
22222  E 
+1

명확하게 설명 할 수 있습니까? 또한, 어떤 RDBMS –

+0

RDBMS, 제발? 이것은 OLAP 함수가있는 구현에서 더 쉽습니다 ... 그리고 일치시킬 _actual_ 열을 나열하십시오. 그것은'ID'가 어디에서 오는지, Order 열 (사이드 노트 - SQL의 '예약어'다음에 테이블/컬럼의 이름을 지정하는 것은 권장하지 않음)입니다. –

+0

Sql Server, 예제를 추가했습니다 – CaffGeek

답변

2

되지 않음을 가장 효율적으로, 또는 우아한하지만 작품!

데이터 설정 :

CREATE TABLE LookupTable (Customer int, Code nvarchar(1), OrderCol int) 
CREATE TABLE DataTable (Customer int, Code nvarchar(1)) 

insert LookupTable values (12345,'A',1),(12345,'B',2),(12345,'C',3),(12345,'D',4),(12345,'E',5),(22222,'A',1),(22222,'B',2),(22222,'D',4),(22222,'E',5) 
insert DataTable values (12345,'B'),(12345,'D'),(22222,'B'),(22222,'D') 

select * from LookupTable 
select * from DataTable 

쿼리 :

;with LookupCte as (
    SELECT *  
     , ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY OrderCol ASC) AS LookUpOrder 
    FROM LookupTable 
) 
, DataCTE as (
    SELECT dt.Customer 
     , dt.Code 
     , lu.LookUpOrder 
     , (lu.LookUpOrder - 1) AS OrderColNVe 
     , (lu.LookUpOrder + 1) AS OrderColPVe 
     , ROW_NUMBER() OVER (PARTITION BY dt.Customer ORDER BY dt.Code ASC) AS DataCteRowNumber 
    FROM DataTable dt 
    INNER JOIN LookupCte lu 
     ON lu.Customer = dt.Customer 
     AND lu.Code = dt.Code 

) 
, UnionCTE As (

    SELECT d.Customer 
     , d.Code 
     , d.DataCteRowNumber 
     , 1 AS [CustomOrder] 
    FROM DataCTE d 

    UNION ALL 

    SELECT lt.Customer 
     , lt.Code 
     , d.DataCteRowNumber 
     , 2 AS [CustomOrder] 
    FROM DataCTE d 
    INNER JOIN LookupCte lt on lt.Customer = d.Customer 
     AND lt.LookUpOrder = d.OrderColNVe 

    UNION ALL 

    SELECT lt.Customer 
     , lt.Code 
     , d.DataCteRowNumber 
     , 3 AS [CustomOrder] 
    FROM DataCTE d 
    INNER JOIN LookupCte lt on lt.Customer = d.Customer 
     AND lt.LookUpOrder = d.OrderColPVe 
) 
SELECT u.Customer 
    , u.Code 
FROM UnionCTE u 
ORDER BY u.Customer, u.DataCteRowNumber, u.CustomOrder 

을 제공합니다 :

Customer Code 
----------- ---- 
12345  B 
12345  A 
12345  C 
12345  D 
12345  C 
12345  E 
22222  B 
22222  A 
22222  D 
22222  D 
22222  B 
22222  E 

(12 row(s) affected) 
+0

I 주문에서 단지 +/- 1 수 없다. 틈이있다. – CaffGeek

+0

답변이 업데이트되었고, 다른 CTE가 추가되었습니다. – Paddy

0

편집 : 순서 필드에 차이가있는 경우, row_Number()에 새 열을 생성

;with c as (
    Select d.Customer 
     , d.code 
     , l.order 
    from Data as d 
    inner join Lookup as l 
    on d.customer = l.Customer 
     and d.Code = l.Code 
    ) 
    select 
     c.Customer 
      , C.Code 
    from c 
    union all 
    Select 
     , c.Customer 
     , l.code 
    from c 
    inner join lookup as l 
    on c.Customer = l.Customer 
     and c.Order = l.Order + 1 
    Select 
     , c.Customer 
     , l.code 
    from c 
    inner join lookup as l 
    on c.Customer = l.Customer 
     and c.Order = l.Order - 1 
+0

주문에서 단지 +/- 1 수 없으며, 간격이 있습니다. – CaffGeek