如何删除列中两个数值之间的所有行

How to delete all rows between two number values in a column

我有一个包含两列的 table,idtyp:

DECLARE @tb1 AS TABLE (id INT, typ INT)
INSERT INTO @tb1
(
    id,
    typ
)
VALUES
(1,1),(2,3),(3,2),(4,3),(5,1),(6,2),(7,3),(8,3),(9,1)
,(10,3),(11,3),(12,3),(13,2),(14,3),(15,1)

查看按 id 排序的行时,我想删除 typ = 1 行和下 typ = 2 行之间的所有行。

我想要这个结果:

id          typ
----------- -----------
1           1
3           2
4           3
5           1
6           2
7           3
8           3
9           1
13          2
14          3
15          1

这个查询应该有效

delete from @tb1 where id < 13 and id > 9

删除典型值介于 10 和 12 之间的 [包括边框]

试试这个

DECLARE @idtype1 int, @idtype2 int

DECLARE type_cursor CURSOR FOR   
SELECT a.ID as ID_TYPE_1, b.ID as ID_TYPE_2  
FROM (SELECT ID, ROW_NUMBER() OVER(ORDER BY_ID) AS RN
    FROM TABLE WHERE TYPE = 1) a
INNER JOIN (SELECT ID, ROW_NUMBER() OVER(ORDER BY_ID) AS RN
        FROM TABLE WHERE TYPE = 2) b
    ON a.RN = b.RN

OPEN type_cursor  

FETCH NEXT FROM type_cursor   
INTO @idtype1, @idtype2  

WHILE @@FETCH_STATUS = 0  
BEGIN  
    DELETE FROM TABLE WHERE ID BETWEEN @idtype1 AND @idtype2

END

这是一道经典的空白和孤岛问题类型的问题。 我建议你通读这篇优秀的 article on gaps and islands。

您可以使用如下查询 See working demo

;
with BoundarySuspects as 
(
    select 
        a.*, 
        seqNumber=row_number() over( order by id asc)
    from @tb1 a
    where a.typ=1 or a.typ=2 
 ),
 GapMap as
 (
     select 
        GapFrom= a.id,
        GapTill= b.id
    from BoundarySuspects a
         join
         BoundarySuspects b
        on a.typ=1 and b.typ=2 and b.seqNumber=a.seqNumber+1 
 )
    select 
        t.* 
     from @tb1 t 
         left join 
     GapMap g
         on t.id >GapFrom and t.id <GapTill
     where GapFrom is NULL

首先,您必须确定要删除的内容的边界:

SELECT
    T1.id as StartId,
    (SELECT MIN(T2.id) from @tb1 T2 WHERE T1.id < T2.id and T2.typ = 2) as EndId
from @tb1 T1
WHERE T1.typ = 1

结果:

StartId  EndId
1        3
5        6
9        13
15       NULL

然后您可以在 CTE(通用 Table 表达式)中使用此查询来执行实际删除操作:

DECLARE @tb1 AS TABLE (id INT, typ int)
INSERT INTO @tb1 (id, typ)
       VALUES (1,1),(2,3),(3,2),(4,3),(5,1),(6,2),(7,3),(8,3),(9,1),(10,3),(11,3),(12,3),(13,2),(14,3),(15,1)

;WITH ranges AS (
    SELECT
        T1.id as StartId,
        (SELECT MIN(T2.id) from @tb1 T2 WHERE T1.id < T2.id and T2.typ = 2) as EndId
    FROM @tb1 T1
    WHERE T1.typ = 1
)
DELETE T3
FROM @tb1 T3
INNER JOIN ranges ON T3.id > ranges.StartId and T3.id < ranges.EndId

SELECT * FROM @tb1