Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何合并不同表中的范围_Sql_Sql Server_Tsql - Fatal编程技术网

Sql 如何合并不同表中的范围

Sql 如何合并不同表中的范围,sql,sql-server,tsql,Sql,Sql Server,Tsql,给出以下两个表格: 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

给出以下两个表格:

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
在SQLServer2008上使用T-SQL获得以下结果的最佳方法是什么

“从/到”范围是连续的,没有间隙,下一个“从”始终与上一个“到”具有相同的值


下面的查询查找最小范围,然后再次从表中提取值:

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

首先,我声明的数据与您发布的数据相似。如果我所做的任何假设是错误的,请纠正我。最好是在问题中发表你自己的声明,这样我们都在使用相同的数据

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查询,用于生成您的预期结果:

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

谢谢你的回答,但我最后使用了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

窃取@isme的数据设置,我写了以下内容:

;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


然后,最终的查询将每对相邻的行组合在一起,并连接回原始表,以查找每一行中哪些行与所选范围重叠。

我无法编译此查询。您是如何设置测试数据的?使用我的数据设置,这仍然无法为我编译。在您的查询副本中,我将所有出现的T1替换为[@T1],将所有出现的T2替换为[@T2],并在执行时收到此语法错误:Msg 156,级别15,状态1,第34行关键字“from”附近的语法不正确。我删除了关于结果集不同的注释,因为它们是相同的。
;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]