在具有特定值的其他记录之前添加新行
Adding a new row before other records that have specific value
我有以下 table:
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),它在 State == 0 的每一行之前插入一个新行。新行应该有 DateTime = TheRowOfInterest(datetime) - 1 秒和 State = 1.
TheRowOfInterest 是 State == 0 的每一行。
重要约束:仅当先前记录的状态 == 1 时才应添加新行。
结果 table 如下所示:
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
我知道我需要使用 window-ing 函数,但还没有完成,欢迎提出任何建议。
更多信息:
- Id 在结果中没有任何作用 table
- Id可能不是连续的
- 我正在使用 SQL Server 2014
这是创建语句和示例数据
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)
这是一个非常简单的解决方案。您还没有发布您尝试过的内容,这在发布问题时非常重要;这意味着志愿者知道您已经付出了一些努力,并且您不希望您为他们做他们的工作。
无论如何,正如我所说,这是通过使用 CTE LAG
和 UNION 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 的评论;不要使用关键字作为列名。 state
和 datetime
都是 SQL 服务器中的关键字。
如果您知道标识值是连续的,那么您可以像这样简单地将 table 与其自身连接起来:
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;
您也可以在此处查看 fiddle
我有以下 table:
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),它在 State == 0 的每一行之前插入一个新行。新行应该有 DateTime = TheRowOfInterest(datetime) - 1 秒和 State = 1.
TheRowOfInterest 是 State == 0 的每一行。
重要约束:仅当先前记录的状态 == 1 时才应添加新行。
结果 table 如下所示:
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
我知道我需要使用 window-ing 函数,但还没有完成,欢迎提出任何建议。
更多信息:
- Id 在结果中没有任何作用 table
- Id可能不是连续的
- 我正在使用 SQL Server 2014
这是创建语句和示例数据
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)
这是一个非常简单的解决方案。您还没有发布您尝试过的内容,这在发布问题时非常重要;这意味着志愿者知道您已经付出了一些努力,并且您不希望您为他们做他们的工作。
无论如何,正如我所说,这是通过使用 CTE LAG
和 UNION 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 的评论;不要使用关键字作为列名。 state
和 datetime
都是 SQL 服务器中的关键字。
如果您知道标识值是连续的,那么您可以像这样简单地将 table 与其自身连接起来:
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;
您也可以在此处查看 fiddle