在其他具有特定值的记录之前添加新行

时间:2018-07-16 10:51:32

标签: sql-server tsql gaps-and-islands

我有下表:

Id  | DateTime            | State
1   | 2018-07-16 10:00:00 | 0
2   | 2018-07-16 10:15:34 | 1
3   | 2018-07-16 10:21:12 | 0
4   | 2018-07-16 10:32:45 | 1
5   | 2018-07-16 10:44:05 | 0

我需要一个查询(t-sql),在状态== 0的每一行之前插入新行。新行应具有DateTime = TheRowOfInterest(datetime)-1秒和State = 1。

TheRowOfInterest是状态== 0的每一行。

重要约束:仅当前一条记录的State == 1时,才应添加新行。

结果表如下:

DateTime            | State
2018-07-16 10:00:00 | 0
2018-07-16 10:15:34 | 1
2018-07-16 10:21:11 | 1      <<<
2018-07-16 10:21:12 | 0
2018-07-16 10:32:45 | 1
2018-07-16 10:44:04 | 1      <<<
2018-07-16 10:44:05 | 0

我知道我需要使用开窗功能,但还没走太远,因此欢迎提出任何建议。

更多信息:

  • 该ID在结果表中不起作用
  • 该ID可能不是连续的
  • 我正在使用SQL Server 2014

这是Create语句和示例数据

CREATE TABLE [dbo].[SwitchSeries](
    [Id] [int] NOT NULL,
    [DateTime] [datetime2](7) NOT NULL,
    [State] [tinyint] NOT NULL
) 

已填充示例数据:

INSERT INTO SwitchSeries VALUES
    (1, '2018-07-16 10:00:00', 0),
    (2, '2018-07-16 10:15:34', 1),
    (3, '2018-07-16 10:21:12', 0),
    (4, '2018-07-16 10:32:45', 1),
    (5, '2018-07-16 10:44:05', 0)

2 个答案:

答案 0 :(得分:1)

这是一个非常简单的解决方案。您尚未发布您尝试过的内容,这在发布问题时非常重要;这意味着志愿者知道您已经付出了很多努力,并且不希望您为他们做他们的工作。

无论如何,正如我所说,这是通过使用CTE,LAGUNION ALL来实现的:

WITH CTE AS(
    SELECT *,
           LAG([State]) OVER (ORDER BY [datetime] ASC) AS PreviousState
    FROM dbo.SwitchSeries)
SELECT [DateTime], [State]
FROM CTE
UNION ALL
SELECT DATEADD(SECOND,-1,[DateTime]), 1
FROM CTE
WHERE [State] = 0
  AND PreviousState = 1
ORDER BY [DateTime];

但是,我完全同意WhatsThePoint的评论;不要使用关键字作为列名。 statedatetime都是SQL Server中的关键字。

答案 1 :(得分:1)

如果您知道标识值是连续的,则可以像这样将表本身与表连接起来:

select DateAdd(ss, -1, s2.DateTime), 1
from SwitchSeries s1 inner join SwitchSeries s2 on s1.Id = s2.Id - 1
where s1.State = 1 and s2.State = 0;

您也可以在这里查看小提琴

SQL Fiddle