根据条件将一列转换为两列
Convert one column to two column based on condition
我有一个 table 看起来像这样的:
TagName DateTime value
HA_06_ON 2020-07-07 08:52:14 1
HA_06_ON 2020-07-07 09:01:42 0
HA_06_ON 2020-07-07 09:02:17 1
HA_06_ON 2020-07-07 09:32:55 0
HA_06_ON 2020-07-07 09:33:21 1
HA_06_ON 2020-07-07 09:35:02 0
HA_06_ON 2020-07-07 09:35:27 1
HA_06_ON 2020-07-07 09:35:44 0
HA_06_ON 2020-07-07 10:10:32 1
HA_06_ON 2020-07-07 10:10:40 0
我想根据值(值 = 1 ==> 开始时间,值 = 0 ==> 结束时间)将此 table 转换为此值。
TagName StartTime EndTime
HA_06_ON 2020-07-07 08:52:14 2020-07-07 09:01:42
HA_06_ON 2020-07-07 09:02:17 2020-07-07 09:32:55
....
我曾尝试在 select 语句中使用 case when 但 return 像这样在每一列上都为 null
TagName StartTime EndTime
HA_06_ON 2020-07-07 08:57:07 NULL
HA_06_ON NULL 2020-07-07 09:01:42
HA_06_ON 2020-07-07 09:02:17 NULL
HA_06_ON NULL 2020-07-07 09:32:55
HA_06_ON 2020-07-07 09:33:21 NULL
HA_06_ON NULL 2020-07-07 09:35:02
由于您此处没有分组列,我们必须做出一个假设:我们可以假设如果我们按日期排序,1 和 0 将交替出现,从而处理您的数据。否则没有解决方案,因为我们不知道如何将 1 与 0 相关联。
鉴于我们可以假定此顺序,我们可以使用 lag()
或 lead()
来执行此操作。请注意,这假设您从 1 开始,并且每个 1 都有对应的 0。如果最后一个 1 没有对应的 0,则该行的 EndTime 将为空。
select u.TagName,
u.StartTime,
u.EndTime
from (
select TagName,
StartTime = [DateTime] ,
EndTime = lead([DateTime], 1) over
(
partition by TagName
order by [Datetime] asc
),
value
from t
) u
where u.value = 1
有多种方法可以解决这个问题。如果我假设这些值是完全交错的,一种方法是聚合:
select tagname, min(datetime) as starttime, max(datetime) as endtime
from (select t.*,
row_number() over (partition by tagname, value order by datetime) as seqnum
from t
) t
group by tagname, seqnum;
只是因为我没有看到 sum() over
选项
例子
Select TagName
,StartTime = min(DateTime)
,EndTime = max(DateTime)
From (
Select *
,Grp = sum(value) over (partition by TagName order by DateTime)
From @YourTable
) A
Group By TagName,Grp
Returns
TagName StartTime EndTime
HA_06_ON 2020-07-07 08:52:14.000 2020-07-07 09:01:42.000
HA_06_ON 2020-07-07 09:02:17.000 2020-07-07 09:32:55.000
HA_06_ON 2020-07-07 09:33:21.000 2020-07-07 09:35:02.000
HA_06_ON 2020-07-07 09:35:27.000 2020-07-07 09:35:44.000
HA_06_ON 2020-07-07 10:10:32.000 2020-07-07 10:10:40.000
我有一个 table 看起来像这样的:
TagName DateTime value
HA_06_ON 2020-07-07 08:52:14 1
HA_06_ON 2020-07-07 09:01:42 0
HA_06_ON 2020-07-07 09:02:17 1
HA_06_ON 2020-07-07 09:32:55 0
HA_06_ON 2020-07-07 09:33:21 1
HA_06_ON 2020-07-07 09:35:02 0
HA_06_ON 2020-07-07 09:35:27 1
HA_06_ON 2020-07-07 09:35:44 0
HA_06_ON 2020-07-07 10:10:32 1
HA_06_ON 2020-07-07 10:10:40 0
我想根据值(值 = 1 ==> 开始时间,值 = 0 ==> 结束时间)将此 table 转换为此值。
TagName StartTime EndTime
HA_06_ON 2020-07-07 08:52:14 2020-07-07 09:01:42
HA_06_ON 2020-07-07 09:02:17 2020-07-07 09:32:55
....
我曾尝试在 select 语句中使用 case when 但 return 像这样在每一列上都为 null
TagName StartTime EndTime
HA_06_ON 2020-07-07 08:57:07 NULL
HA_06_ON NULL 2020-07-07 09:01:42
HA_06_ON 2020-07-07 09:02:17 NULL
HA_06_ON NULL 2020-07-07 09:32:55
HA_06_ON 2020-07-07 09:33:21 NULL
HA_06_ON NULL 2020-07-07 09:35:02
由于您此处没有分组列,我们必须做出一个假设:我们可以假设如果我们按日期排序,1 和 0 将交替出现,从而处理您的数据。否则没有解决方案,因为我们不知道如何将 1 与 0 相关联。
鉴于我们可以假定此顺序,我们可以使用 lag()
或 lead()
来执行此操作。请注意,这假设您从 1 开始,并且每个 1 都有对应的 0。如果最后一个 1 没有对应的 0,则该行的 EndTime 将为空。
select u.TagName,
u.StartTime,
u.EndTime
from (
select TagName,
StartTime = [DateTime] ,
EndTime = lead([DateTime], 1) over
(
partition by TagName
order by [Datetime] asc
),
value
from t
) u
where u.value = 1
有多种方法可以解决这个问题。如果我假设这些值是完全交错的,一种方法是聚合:
select tagname, min(datetime) as starttime, max(datetime) as endtime
from (select t.*,
row_number() over (partition by tagname, value order by datetime) as seqnum
from t
) t
group by tagname, seqnum;
只是因为我没有看到 sum() over
选项
例子
Select TagName
,StartTime = min(DateTime)
,EndTime = max(DateTime)
From (
Select *
,Grp = sum(value) over (partition by TagName order by DateTime)
From @YourTable
) A
Group By TagName,Grp
Returns
TagName StartTime EndTime
HA_06_ON 2020-07-07 08:52:14.000 2020-07-07 09:01:42.000
HA_06_ON 2020-07-07 09:02:17.000 2020-07-07 09:32:55.000
HA_06_ON 2020-07-07 09:33:21.000 2020-07-07 09:35:02.000
HA_06_ON 2020-07-07 09:35:27.000 2020-07-07 09:35:44.000
HA_06_ON 2020-07-07 10:10:32.000 2020-07-07 10:10:40.000