2012-04-06 59 views
5

給予下列2個表合併範圍:如何從不同的表

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 

什麼是讓下面的結果,使用SQL Server 2008的T-SQL的最佳方式?

的從/到的範圍是連續的(沒有間隙)和下一總是具有相同的值作爲先前

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 

回答

4

首先我聲明的數據看起來像您發佈的數據。如果我所做的任何假設都是錯誤的,請糾正我。更好的做法是在問題中發佈自己的聲明,這樣我們就可以使用相同的數據。

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'); 

這裏是我的選擇查詢生成您預期的結果:

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

結果第5行錯誤。現在是固定的。謝謝。 – pvieira 2012-04-06 18:31:00

+0

我刪除了關於結果集不同的評論,現在他們是相同的。 – 2012-04-08 13:22:56

0

的下面查詢查找最小範圍內,則將值再次從表中取出:

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

我不能使這個查詢編譯。你是如何設置你的測試數據的? – 2012-04-06 18:22:51

+0

它錯過了一個GROUP BY,再試一次,它現在有效。 – GavinCattell 2012-04-06 18:52:27

+0

這仍然不能編譯我使用我的數據設置。在你查詢的副本中,我用'[@ T1]'替換了所有'T1',並用'[@ T2]'替換了所有出現的'T2',並且在執行時收到了這個語法錯誤:'Msg 156,Level 15 ,狀態1,行34 關鍵字'from'附近的語法不正確。 – 2012-04-08 14:23:54

0

感謝您的答案,但我使用CTE,wgich我認爲是清潔結束。

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

偷@國際音樂教育學會的數據設置,我寫道:

;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] 

也就是說,您創建一個包含所有時段的可能端點(EPs)的一組,那麼你「之類的」併爲每一個分配一個行號(OrderedEPs)。

然後最後一個查詢將每個「相鄰」行對組合在一起,然後連接回原始表以查找每個行的哪些行與選定範圍重疊。