SQL Server:根据当前行中的值删除先前的行

时间:2019-03-27 12:04:59

标签: sql sql-server tsql

我有一个包含以下列的表:Author_name,国家/地区和状态。

    Author_name       country       status
-------------------------------------------
1   Author - 1  Country - 1 name    remove
2   Author - 2  Country - 2 name    done
3   Author - 3  Country - 3 name    done
4   Author - 4  Country - 4 name    done
5   Author - 5  Country - 5 name    done
6   Author - 6  Country - 6 name    remove
7   Author - 7  Country - 7 name    remove
8   Author - 8  Country - 8 name    done
9   Author - 9  Country - 9 name    remove
10  Author - 10 Country - 10 name   done

预期功能:遇到“删除”时,必须删除该行,并删除其上方的行。

如果“删除”连续出现,则必须删除顶部的许多行。 “删除”的位置和记录数不是恒定的。

一旦运行了SQL脚本,上表的输出应为:

     Author_name      country        status
-------------------------------------------
2    Author - 2  Country - 2 name    done
3    Author - 3  Country - 3 name    done
10   Author - 10 Country - 10 name   done

希望您了解逻辑。

我尝试使用滞后,光标和其他一些方法。现在我正在尝试while循环。请帮我解决一下这个。这是我的最新代码。

我的数据库是SQL Server,当前正在使用在线编译器:https://rextester.com/l/sql_server_online_compiler

CREATE Table tblAuthors
(
   Author_name nvarchar(50),
   country nvarchar(50),
   prod varchar(50),
   timestamp datetime 
)

Declare @Id int
Set @Id = 1

While @Id <= 10
Begin 
   Insert Into tblAuthors values ('Author - ' + CAST(@Id as nvarchar(10)),
              'Country - ' + CAST(@Id as nvarchar(10)) + ' name', 'done', getdate())
   Print @Id
   Set @Id = @Id + 1
End

update tblAuthors set prod = 'remove' where  Author_name  = 'Author - 1'
update tblAuthors set prod = 'remove' where  Author_name  = 'Author - 6'
update tblAuthors set prod = 'remove' where  Author_name  = 'Author - 7'
update tblAuthors set prod = 'remove' where  Author_name  = 'Author - 9'

SELECT * FROM tblAuthors

select IDENTITY(int, 1,1) as idnt,*  into ##temp_tblAuthors from tblAuthors

select * from ##temp_tblAuthors


DECLARE @intFlag INT = 1
DECLARE @Flag INT = 0
DECLARE  @Author_name nvarchar(50)
DECLARE @country nvarchar(50)
DECLARE  @prod varchar(50)
DECLARE @idnt INT

select @Flag = count(*) from ##temp_tblAuthors

WHILE (@intFlag <=@Flag)
BEGIN

select 
 @idnt = idnt
,@Author_name = Author_name
,@country = country
,@prod = prod 
from ##temp_tblAuthors where idnt = @intFlag

if @prod = 'remove' 
BEGIN 

SELECT  @intFlag
select 
 @idnt = idnt
,@Author_name = Author_name
,@country = country
,@prod = prod 
from ##temp_tblAuthors where idnt = @intFlag-1

DELETE tblAuthors WHERE 
Author_name = @Author_name AND 
country = @country  AND 
prod  = @prod

select 
 @idnt = idnt
,@Author_name = Author_name
,@country = country
,@prod = prod 
from ##temp_tblAuthors where idnt = @intFlag

DELETE tblAuthors WHERE 
Author_name = @Author_name AND 
country = @country  AND 
prod  = @prod



END 

SET @intFlag = @intFlag + 1
END
GO

SELECT * FROM tblAuthors

1 个答案:

答案 0 :(得分:1)

如果您 后退 ,则可以总计“得分”,其中'remove'-1,而'done'有{ {1}}。

+1

示例SQL:

    Author_name   Country             Status    Score
------------------------------------------------------
1   Author - 1    Country - 1 name    remove     2
2   Author - 2    Country - 2 name    done       3
3   Author - 3    Country - 3 name    done       2
4   Author - 4    Country - 4 name    done       1
5   Author - 5    Country - 5 name    done       0
6   Author - 6    Country - 6 name    remove    -1
7   Author - 7    Country - 7 name    remove     0
8   Author - 8    Country - 8 name    done       1
9   Author - 9    Country - 9 name    remove     0
10  Author - 10   Country - 10 name   done       1   <- Start from here

然后,您只想保留比当前得分高的行(仍在向后移动)。

SELECT
  *,
  SUM(CASE WHEN status = 'remove' THEN -1 ELSE 1 END)
    OVER (ORDER BY timestamp DESC, id DESC)
      AS score
FROM
  tblAuthors

您可以使用...

    Author_name   Country             Status    Score   PreviousMax
--------------------------------------------------------------------
1   Author - 1    Country - 1 name    remove     2      3
2   Author - 2    Country - 2 name    done       3      2    <- KEEP
3   Author - 3    Country - 3 name    done       2      1    <- KEEP 
4   Author - 4    Country - 4 name    done       1      1
5   Author - 5    Country - 5 name    done       0      1
6   Author - 6    Country - 6 name    remove    -1      1
7   Author - 7    Country - 7 name    remove     0      1
8   Author - 8    Country - 8 name    done       1      1
9   Author - 9    Country - 9 name    remove     0      1
10  Author - 10   Country - 10 name   done       1      NULL <- KEEP

这也导致您...

WITH
  scored_rows AS
(
  SELECT
    *,
    SUM(CASE WHEN status = 'remove' THEN -1 ELSE 1 END)
      OVER (ORDER BY timestamp DESC, id DESC)
        AS score
  FROM
    tblAuthors
),
  checked_scored_rows AS
(
  SELECT
    *,
    MAX(score)
      OVER (ORDER BY timestamp DESC, id DESC
                ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
           )
             AS previous_max_score
  FROM
    scored_rows
)
SELECT
  *
FROM
  checked_scored_rows
WHERE
  score > COALESCE(previous_max_score, 0)
;

我相信这可以说明您想要什么:https://rextester.com/ZNNB32798