2012-04-17 23 views
5

Ich versuche, zusammen zwei Tabellen zu verknüpfen, aber eine ungerade Anforderung haben.komplizierte SQL Join

Normalerweise würde ich nur verbinden, in dem der Datensatz für die Kunden ist und der Code übereinstimmt

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

Aber was ich brauche, ist auf drei Zeilen aus der Lookup-Tabelle zu tun, zu verbinden. Die ID, die übereinstimmt, und die Zeile davor und danach (falls vorhanden) basierend auf der Sortierreihenfolge in einer anderen Spalte (Bestellung). Ich muss dann das Ergebnis sortieren, mit dem Datensatz, der zuerst übereinstimmt, dann den Suchdatensatz, der zuvor war, und dann den Suchdatensatz, der nach dem übereinstimmenden Datensatz war.

Irgendwelche Gedanken über den besten Weg, dies zu erreichen?

Beispiel:

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

Können Sie ein Beispiel zur Klärung geben? Auch welche RDBMS –

+0

Was RDBMS, bitte? Dies ist einfacher in den Implementierungen, die OLAP-Funktionen haben ... Und könnten Sie bitte auflisten, welche Spalten _actual_ die Übereinstimmungen haben sollen? Wie es ist, ist es unklar, woher 'ID' kommt und die 'Order'-Spalte (Randnotiz - es wird nicht empfohlen, Tabellen/Spalten nach den 'reservierten' Wörtern in SQL zu benennen). –

+0

Sql Server, habe ich ein Beispiel hinzugefügt – CaffGeek

Antwort

2

nicht die effizienteste oder elegant, aber es funktioniert!

Datenaufbau:

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 

Die Abfrage:

;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 

Gibt:

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 kann nicht nur +/- 1 von der Bestellung, gibt es Lücken – CaffGeek

+0

Antwort aktualisiert, fügte ein weiteres CTE - ich gebe zu, das ist v. böse jetzt! – Paddy

0

Edit: Wenn es Lücken in der Reihenfolge Bereich sind, erstellen Sie eine neue Spalte mit 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

Ich kann nicht nur +/- 1 aus der Bestellung, da sind Lücken – CaffGeek