2012-04-17 12 views
5

Próbuję połączyć dwie tabele razem, ale mają dziwne wymagania.Skomplikowane SQL Dołącz

Normalnie bym po prostu dołączyć, gdzie płyta jest dla danego klienta i kod pasuje

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

Jednak to, co muszę zrobić, to dołączyć na trzech wierszy z tabeli. Identyfikator, który pasuje, oraz wiersz przed i po (jeśli istnieją) oparty na porządku sortowania w innej kolumnie (Zamówienie). Następnie muszę posortować wynik, z rekordem, który pasuje pierwszy, a następnie rekordem wyszukiwania, który był wcześniej, a następnie rekordem wyszukiwania, który był po dopasowanym rekordzie.

Jakieś przemyślenia na temat najlepszego sposobu osiągnięcia tego?

Przykład:

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

Czy możesz podać przykład, aby wyjaśnić? Także, który RDBMS –

+0

Co RDBMS, proszę? Jest to łatwiejsze w tych implementacjach, które mają funkcje OLAP ... Czy mógłbyś podać, do czego kolumny _właściwości_, w których chcesz dopasować? Jak to jest, nie jest jasne, skąd pochodzi "ID", a kolumna "Zamówienie" (uwaga dodatkowa - nie zaleca się nadawania nazw tabelom/kolumnom po słowach "zarezerwowanych" w SQL). –

+0

Serwer Sql, dodałem exmaple – CaffGeek

Odpowiedz

2

Nie jest to najbardziej efektywny, lub eleganckie, ale działa!

konfiguracja danych:

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 

Query:

;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 

Daje:

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

nie może po prostu +/- 1 od zamówienia, są luki – CaffGeek

+0

Odpowiedź zaktualizowana, dodano kolejne CTE - Przyznaję, że to jest v. nasty teraz! – Paddy

0

Edycja: Jeśli istnieją luki w zakresie zamówienia, należy utworzyć nową kolumnę z 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

Nie mogę po prostu +/- 1 od zamówienia, są luki – CaffGeek

Powiązane problemy