2012-04-06 23 views
5

uzyskując następujące 2 tabele:Jak scalić zakresów z różnych tabel

T1 
------------------ 
From | To | Value 
------------------ 
10 | 20 | XXX 
20 | 30 | YYY 
30 | 40 | ZZZ 


T2 
------------------ 
From | To | Value 
------------------ 
10 | 15 | AAA 
15 | 19 | BBB 
19 | 39 | CCC 
39 | 40 | DDD 

Jaki jest najlepszy sposób, aby uzyskać wynik poniżej, przy użyciu T-SQL na SQL Server 2008?

From/zakresów są sekwencyjne (nie ma przerwy) i następnego Z ma zawsze tę samą wartość, co poprzednia Do

Desired result 
------------------------------- 
From | To | Value1 | Value2 
------------------------------- 
10 | 15 | XXX | AAA 
15 | 19 | XXX | BBB 
19 | 20 | XXX | CCC 
20 | 30 | YYY | CCC 
30 | 39 | ZZZ | CCC 
39 | 40 | ZZZ | DDD 

Odpowiedz

4

Najpierw deklaruję dane, które wyglądają jak dane, które wysłałeś. Proszę poprawić mnie, jeśli moje założenia są błędne. Lepiej byłoby zamieścić własną deklarację w pytaniu, abyśmy wszyscy pracowali z tymi samymi danymi.

DECLARE @T1 TABLE (
    [From] INT, 
    [To] INT, 
    [Value] CHAR(3) 
); 

INSERT INTO @T1 (
    [From], 
    [To], 
    [Value] 
) 
VALUES 
    (10, 20, 'XXX'), 
    (20, 30, 'YYY'), 
    (30, 40, 'ZZZ'); 

DECLARE @T2 TABLE (
    [From] INT, 
    [To] INT, 
    [Value] CHAR(3) 
); 

INSERT INTO @T2 (
    [From], 
    [To], 
    [Value] 
) 
VALUES 
    (10, 15, 'AAA'), 
    (15, 19, 'BBB'), 
    (19, 39, 'CCC'), 
    (39, 40, 'DDD'); 

Oto moja kwerenda wybierająca wygenerować oczekiwane wyniki:

SELECT 
    CASE 
    WHEN [@T1].[From] > [@T2].[From] 
    THEN [@T1].[From] 
    ELSE [@T2].[From] 
    END AS [From], 
    CASE 
    WHEN [@T1].[To] < [@T2].[To] 
    THEN [@T1].[To] 
    ELSE [@T2].[To] 
    END AS [To], 
    [@T1].[Value], 
    [@T2].[Value] 
FROM @T1 
INNER JOIN @T2 ON 
    (
    [@T1].[From] <= [@T2].[From] AND 
    [@T1].[To] > [@T2].[From] 
) OR 
    (
    [@T2].[From] <= [@T1].[From] AND 
    [@T2].[To] > [@T1].[From] 
); 
+0

Wynik wiersz 5 był nieprawidłowy. Naprawiono teraz. Dzięki. – pvieira

+0

Usunąłem swój komentarz o tym, że zestawy wyników są różne, teraz, gdy są takie same. –

0

poniżej zapytanie znajdzie niewielkiego przekroju poprzecznego, a następnie odbiera wartości ponownie z tabel:

SELECT ranges.from, ranges.to, T1.Value, T2.Value 
FROM (SELECT all_from.from, min(all_to.to) as to 
    FROM (SELECT T1.FROM 
     FROM T1 
     UNION 
     SELECT T2.FROM 
     FROM T2) all_from 
    JOIN (SELECT T1.TO 
     FROM T1 
     UNION 
     SELECT T2.FROM 
     FROM T2) all_to ON all_from.from < all_to.to 
    GROUP BY all_from.from) ranges 
JOIN T1 ON ranges.from >= T1.from AND ranges.to <= T1.to 
JOIN T2 ON ranges.from >= T2.from AND ranges.to <= T2.to 
ORDER BY ranges.from 
+1

Nie mogę skompilować tego zapytania. Jak skonfigurowałeś swoje dane testowe? –

+0

Brakowało GROUP BY, spróbuj ponownie, działa teraz. – GavinCattell

+0

To nadal nie kompiluje się dla mnie przy użyciu mojej konfiguracji danych. W kopii twojego zapytania zastąpiłem wszystkie wystąpienia 'T1' przez' [@ T1] 'i wszystkie wystąpienia' T2' za pomocą '[@ T2]' i otrzymałem ten błąd składni podczas wykonywania: 'Msg 156, Poziom 15 , State 1, Line 34 Niepoprawna składnia w pobliżu słowa kluczowego "from'." –

0

Dzięki za odpowiedzi, ale skończyło użyciu CTE, wgich moim zdaniem jest czystsze.

DECLARE @T1 TABLE ([From] INT, [To] INT, [Value] CHAR(3)); 
DECLARE @T2 TABLE ([From] INT, [To] INT, [Value] CHAR(3)); 

INSERT INTO @T1 ( [From], [To], [Value]) VALUES (10, 20, 'XXX'), (20, 30, 'YYY'), (30, 40, 'ZZZ'); 
INSERT INTO @T2 ( [From], [To], [Value]) VALUES (10, 15, 'AAA'), (15, 19, 'BBB'), (19, 39, 'CCC'), (39, 40, 'DDD'); 

;with merged1 as 
(
    select 
     t1.[From] as from1, 
     t1.[to] as to1, 
     t1.Value as Value1, 
     t2.[From] as from2, 
     t2.[to] as to2, 
     t2.Value as Value2 
    from @t1 t1 
    inner join @T2 t2 
     on t1.[From] < t2.[To] 
     and t1.[To] >= t2.[From] 

) 
,merged2 as 
(
    select 
      case when from2>=from1 then from2 else from1 end as [From] 
     ,case when to2<=to1 then to2 else to1 end as [To] 
     ,value1 
     ,value2 
    from merged1 
) 
select * from merged2 
3

Kradzież konfigurację danych @ ISME za napisałem następujący:

;With EPs as (
    select [From] as EP from @T1 
    union 
    select [To] from @T1 
    union 
    select [From] from @T2 
    union 
    select [To] from @T2 
), OrderedEndpoints as (
    select EP,ROW_NUMBER() OVER (ORDER BY EP) as rn from EPs 
) 
select 
    oe1.EP, 
    oe2.EP, 
    t1.Value, 
    t2.Value 
from 
    OrderedEndpoints oe1 
     inner join 
    OrderedEndpoints oe2 
     on 
      oe1.rn = oe2.rn - 1 
     inner join 
    @T1 t1 
     on 
      oe1.EP < t1.[To] and 
      oe2.EP > t1.[From] 
     inner join 
    @T2 t2 
     on 
      oe1.EP < t2.[To] and 
      oe2.EP > t2.[From] 

Oznacza to, że należy utworzyć zestaw zawierający wszystkich możliwych punktów końcowych okresach (EPs), a następnie "sort" te i przypisz każdemu numer wiersza (OrderedEPs).

Następnie ostateczne zapytanie składa każdą "sąsiednią" parę wierszy ze sobą i łączy się z oryginalnymi tabelami, aby znaleźć wiersze z każdego z nich pokrywające się z wybranym zakresem.

Powiązane problemy