【问题标题】:How To Identify Overlap Number Ranges Considering Range Type?如何识别考虑范围类型的重叠数范围?
【发布时间】:2017-05-18 09:06:58
【问题描述】:

我有两个表 TABLE1(记录列表)和 TABLE2(要检查的我的号码范围)

考虑到 TypeId,如何识别 TABLE2 中的重叠范围/行?

目标

RECORDS TABLE
+-----------------+-----------------+-------------------+
+     typeId      + tbl1_NumberFrom + tbl1_NumberTo     +
+-----------------+-----------------+-------------------+
+       1         +      1          +        5          +
+       1         +      8          +        10         +
+       1         +      15         +        20         +
+       2         +      4          +        7          +
+       2         +      9          +        10         +
+       2         +      11         +        20         +
+-----------------+-----------------+-------------------+

MY RANGES TABLE TO CHECK
+-----------------+-----------------+-------------------+
+      typeId     + My_NumberFrom   + My_NumberTo       +
+-----------------+-----------------+-------------------+
+      1          +      1          +        3          +
+      1          +      6          +        8          +
+      1          +      11         +        12         +
+      2          +      1          +        3          +
+      2          +      6          +        8          +
+      2          +      10         +        10         +
+-----------------+-----------------+-------------------+

REQUIRED RESULT AS FOLLOW:
+-----------------+-----------------+-------------------+-------------------+
+      typeId     + My_NumberFrom   + My_NumberTo       +   IsOverlapping   +
+-----------------+-----------------+-------------------+-------------------+
+      1          +      1          +        3          +        YES        +
+      2          +      1          +        3          +        NO         +
+      1          +      6          +        8          +        YES        +
+      2          +      6          +        8          +        YES        +
+      1          +      11         +        12         +        NO         +
+      2          +      10         +        10         +        YES        +
+-----------------+-----------------+-------------------+-------------------+

更多,

以上表格的 SQL

IF OBJECT_ID('tempdb.dbo.#dbtable', 'U') IS NOT NULL  DROP TABLE #dbtable; 
SELECT * INTO #dbtable FROM 
    (SELECT 1 typeId, 1 AS tbl1_NumberFrom, 5 AS tbl1_NumberTo
    UNION ALL 
    SELECT 1 typeId, 8 AS tbl1_NumberFrom, 10 AS tbl1_NumberTo
    UNION ALL 
    SELECT 1 typeId, 15 AS tbl1_NumberFrom, 20 AS tbl1_NumberTo 
    UNION ALL 
    SELECT 2 typeId, 4  AS tbl1_NumberFrom, 7 AS tbl1_NumberTo 
    UNION ALL 
    SELECT 2 typeId, 9 AS tbl1_NumberFrom, 10 AS tbl1_NumberTo 
    UNION ALL 
    SELECT 2 typeId, 11 AS tbl1_NumberFrom, 20 AS tbl1_NumberTo) 
AS dbTable

IF OBJECT_ID('tempdb.dbo.#MyRanges', 'U') IS NOT NULL  DROP TABLE #MyRanges; 
SELECT * INTO #MyRanges FROM 
    (SELECT 1 typeId, 1 AS myr_NumberFrom, 3 AS myr_NumberTo
    UNION ALL 
    SELECT 1 typeId, 6 AS myr_NumberFrom, 8 AS myr_NumberTo 
    UNION ALL 
    SELECT 1 typeId, 11 AS myr_NumberFrom, 12 AS myr_NumberTo
    UNION ALL
    SELECT 2 typeId, 1 AS My_NumberFrom, 3 AS myr_NumberTo
    UNION ALL 
    SELECT 2 typeId, 6 AS myr_NumberFrom, 8 AS myr_NumberTo 
    UNION ALL 
    SELECT 2 typeId, 10 AS myr_NumberFrom, 10 AS myr_NumberTo)
AS MyList


SELECT * FROM #dbtable t
SELECT * FROM #MyRanges m

请推荐,

非常感谢!!

【问题讨论】:

  • 最后一行 (2-10-10) 不应该是 YES 吗?它与 2-9-10 重叠。
  • @NemanjaPerovic 哦,是的,你是对的.. 修改了问题谢谢!!!

标签: sql sql-server


【解决方案1】:
SELECT DISTINCT m.*,
CASE ISNULL(t.typeId,0) WHEN 0 THEN 'NO' ELSE 'YES' END AS IsOverlapping   
 FROM #MyRanges m
LEFT OUTER JOIN #dbtable t
ON t.typeId = m.typeId
AND 
(t.tbl1_NumberFrom BETWEEN m.myr_NumberFrom AND m.myr_NumberTo
OR
t.tbl1_NumberTo BETWEEN m.myr_NumberFrom AND m.myr_NumberTo)

【讨论】:

    【解决方案2】:

    检查两个范围是否重叠的方法是测试一个在另一个结束之前开始,而另一个在第一个结束之前开始。
    这是在 t-sql 中执行此操作的一种方法:

    SELECT  typeId, 
            myr_NumberFrom, 
            myr_NumberTo,
            CASE WHEN EXISTS
            (
                SELECT 1
                FROM #dbtable t
                WHERE t.typeId = m.typeId
                AND tbl1_NumberFrom <= myr_NumberTo
                AND tbl1_NumberTo >= myr_NumberFrom
            ) THEN 'Yes'
            ELSE 'No'
            END As IsOverlapping   
    FROM #MyRanges m
    

    结果:

    typeId  myr_NumberFrom  myr_NumberTo    IsOverlap
    1       1               3               Yes
    1       6               8               Yes
    1       11              12              No
    2       1               3               No
    2       6               8               Yes
    2       10              10              Yes
    

    改为左连接而不是子查询:

    SELECT  m.typeId, 
            myr_NumberFrom, 
            myr_NumberTo,
            CASE WHEN t.typeId IS NOT NULL THEN 
                'Yes'
            ELSE
                'No'
            END As IsOverlapping   
    FROM #MyRanges m
    LEFT JOIN #dbtable t ON m.typeId = t.typeId
                        AND myr_NumberFrom <= tbl1_NumberTo
                        AND myr_NumberTo >= tbl1_NumberFrom
    

    结果相同,现场演示已更新。

    You can see a live demo on rextester.

    【讨论】:

    • 不慢吗?在使用 select 以防万一?
    • 子查询可能比连接慢。如果您愿意,可以很容易地转换为加入...
    • 好了,现在你还有一个左连接。
    【解决方案3】:

    我的答案与你其他问题的答案几乎相同。

    有四种类型的重叠。您需要两个条件才能找到重叠。其他答案忘记了 myr_numberfrom tbl1_numberto 的重叠类型。

    Select distinct m.typeId, m.Myr_NumberFrom,m.Myr_NumberTo, 
            case when t.tbl1_NumberFrom is null then 'No' else 'yes' end isOverlapping
    from #MyRanges m
    left join #dbtable t on m.typeId = t.typeId
                    and (m.Myr_NumberFrom between t.tbl1_NumberFrom and t.tbl1_NumberTo
                    or  t.tbl1_NumberFrom between m.Myr_NumberFrom and m.Myr_Numberto)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-26
      • 1970-01-01
      • 2010-12-14
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多