SQL - 将许多类别分成几个类别
SQL - Group many categories into few categories
我有一个问题。它 returns 行,一列是状态列,一列是经过时间列。大约有 8 个状态类别。我想将某些状态及其经过的时间总结为 ~3 类。有人知道我该怎么做吗?
这是当前的查询,它按天将条目拆分到 bin 中。
declare @STARDTZ as datetime2
declare @LASTDTZ as datetime2
declare @STARTDT as datetime2
declare @LASTDT as datetime2
set @LASTDT = getdate()
set @STARTDT = DATEADD(dd,-7,getdate())
SET @STARDTZ = DATEADD(dd, DATEDIFF(dd, 0, @STARTDT), 0) --set the start time to 12am (zero) given input datetime
SET @LASTDTZ = DATEADD(dd, DATEDIFF(dd, 0, @LASTDT), 0) --set the stop time to 12am (zero) given input stoptime
;
with dates(dt) as (select @STARDTZ union all select dateadd(day,1,dt) from dates where dt < @LASTDTZ)
select t.Name
,case when t.StartDT>=d.dt then t.StartDT else d.dt end as StartDT
,case when datediff(day,LastDT,dt)=0 then t.LastDT else dateadd(day,1,d.dt) end as LastDT
,datediff(millisecond,case when t.StartDT>=d.dt then t.StartDT else d.dt end
,case when datediff(day,LastDT,dt)=0 then t.LastDT else dateadd(day,1,d.dt) end)/60000.0 as IntervalMin
,t.FullName
,DATEADD(dd, DATEDIFF(dd, 0, dt), 0) as DateBin
from
(
SELECT
CoatingChamberStates.Name as Name
,c.StartDT as StartDT
,c.LastDT as LastDT
,c.IntervalMin
,CoatingChambers.FullName
,DATEADD(dd, DATEDIFF(dd, 0, StartDT), 0) as DateBin
FROM [REO].[dbo].CoatingChamberStateLogs as c
INNER JOIN CoatingChamberStates on c.CoatingChamberStatesID = CoatingChamberStates.CoatingChamberStatesID
INNER JOIN CoatingChambers on c.CoatingChambersID = CoatingChambers.CoatingChambersID
where c.StartDT >= @STARDTZ
and c.LastDT <= @LASTDTZ
) as t
join dates d on d.dt >= cast(t.StartDT as date) and d.dt<=cast(t.LastDT as date)
group by DateBin, StartDT, Name, dt, LastDT, FullName
内容如下returns:
Name StartDT LastDT IntervalMin FullName DateBin
UNKNOWN 2017-04-28 00:05:31.1335380 2017-04-28 11:36:40.1200328 691.1497833 SPECTOR7 2017-04-28 00:00:00.000
UNKNOWN 2017-04-28 00:06:31.6555661 2017-04-28 00:07:31.5121862 0.9976166 LOTUS3 2017-04-28 00:00:00.000
IDLE 2017-04-28 00:07:31.5121862 2017-04-28 11:53:39.7066464 706.1365666 LOTUS3 2017-04-28 00:00:00.000
UNKNOWN 2017-04-28 00:50:32.1654631 2017-04-28 00:51:32.0670071 0.9983666 LOTUS1 2017-04-28 00:00:00.000
RUN_PARTS 2017-04-28 00:51:32.0670071 2017-04-28 00:53:32.0966491 2.0004833 LOTUS1 2017-04-28 00:00:00.000
IDLE 2017-04-28 00:53:32.0966491 2017-04-28 05:50:36.3819295 297.0714166 LOTUS1 2017-04-28 00:00:00.000
RUN_OTHER 2017-04-28 00:53:32.1747858 2017-04-28 12:03:40.0639753 670.1314833 OXFORD2 2017-04-28 00:00:00.000
IDLE 2017-04-28 01:00:32.3043454 2017-04-28 02:26:33.3361640 86.0172000 SPECTOR1 2017-04-28 00:00:00.000
IDLE 2017-04-28 01:50:32.8690160 2017-04-28 07:07:37.3384170 317.0744833 IONTECH 2017-04-28 00:00:00.000
IDLE 2017-04-28 01:57:32.9759673 2017-04-28 02:36:33.6234811 39.0108000 LOTUS8 2017-04-28 00:00:00.000
IDLE 2017-04-28 02:04:33.0037095 2017-04-28 03:10:33.8922959 66.0148166 LOTUS6 2017-04-28 00:00:00.000
UNKNOWN 2017-04-28 02:12:33.2932821 2017-04-28 02:13:33.1640310 0.9978500 SPECTOR6 2017-04-28 00:00:00.000
IDLE 2017-04-28 02:12:33.3089156 2017-04-28 05:27:36.3023807 195.0499000 SPECTOR8 2017-04-28 00:00:00.000
RUN_PARTS 2017-04-28 02:13:33.1640310 2017-04-28 02:31:33.4447516 18.0046666 SPECTOR6 2017-04-28 00:00:00.000
RUN_TEST 2017-04-28 02:26:33.3361640 2017-04-28 03:43:34.4053900 77.0178166 SPECTOR1 2017-04-28 00:00:00.000
IDLE 2017-04-28 02:31:33.4447516 2017-04-28 04:27:35.0346386 116.0265000 SPECTOR6 2017-04-28 00:00:00.000
我想将某些类别的经过时间合并为 3 个类别:"idle"、"running" 和 "waste",例如 "run_parts" 和 "run_test" 将汇总为 "running".
这有意义吗?我该如何处理?谢谢!
您可以使用 case
表达式将名称排序到派生的 table:
中您想要的存储桶中
with dates(dt) as (select @stardtz union all select dateadd(day,1,dt) from dates where dt < @lastdtz)
select
t.Name
,case when t.Startdt>=d.dt then t.Startdt else d.dt end as Startdt
,case when datediff(day,Lastdt,dt)=0 then t.Lastdt else dateadd(day,1,d.dt) end as Lastdt
,datediff(millisecond,case when t.Startdt>=d.dt then t.Startdt else d.dt end
,case when datediff(day,Lastdt,dt)=0 then t.Lastdt else dateadd(day,1,d.dt) end)/60000.0 as IntervalMin
,t.FullName
,dateadd(day, datediff(day, 0, dt), 0) as DateBin
from (
select
case when CoatingChamberStates.Name in ('run_parts','run_test') then 'running'
when CoatingChamberStates.Name = 'unknown' then 'waste'
else CoatingChamberStates.Name
end as Name
,c.Startdt as Startdt
,c.Lastdt as Lastdt
,c.IntervalMin
,CoatingChambers.FullName
,dateadd(day, datediff(day, 0, Startdt), 0) as DateBin
from [reo].[dbo].CoatingChamberStateLogs as c
inner join CoatingChamberStates
on c.CoatingChamberStatesid = CoatingChamberStates.CoatingChamberStatesid
inner join CoatingChambers
on c.CoatingChambersid = CoatingChambers.CoatingChambersid
where c.Startdt >= @stardtz
and c.Lastdt <= @lastdtz
) as t
join dates d
on d.dt >= cast(t.Startdt as date)
and d.dt<=cast(t.Lastdt as date)
group by DateBin, Startdt, dt, Lastdt, FullName, t.Name
或者您可以 select
和 group by
一个 case
表达式而不是 t.Name
:
with dates(dt) as (select @stardtz union all select dateadd(day,1,dt) from dates where dt < @lastdtz)
select
case when t.Name in ('run_parts','run_test') then 'running'
when t.Name = 'unknown' then 'waste'
else t.Name
end as Name
,case when t.Startdt>=d.dt then t.Startdt else d.dt end as Startdt
,case when datediff(day,Lastdt,dt)=0 then t.Lastdt else dateadd(day,1,d.dt) end as Lastdt
,datediff(millisecond,case when t.Startdt>=d.dt then t.Startdt else d.dt end
,case when datediff(day,Lastdt,dt)=0 then t.Lastdt else dateadd(day,1,d.dt) end)/60000.0 as IntervalMin
,t.FullName
,dateadd(day, datediff(day, 0, dt), 0) as DateBin
from (
select
CoatingChamberStates.Name as Name
,c.Startdt as Startdt
,c.Lastdt as Lastdt
,c.IntervalMin
,CoatingChambers.FullName
,dateadd(day, datediff(day, 0, Startdt), 0) as DateBin
from [reo].[dbo].CoatingChamberStateLogs as c
inner join CoatingChamberStates
on c.CoatingChamberStatesid = CoatingChamberStates.CoatingChamberStatesid
inner join CoatingChambers
on c.CoatingChambersid = CoatingChambers.CoatingChambersid
where c.Startdt >= @stardtz
and c.Lastdt <= @lastdtz
) as t
join dates d
on d.dt >= cast(t.Startdt as date)
and d.dt<=cast(t.Lastdt as date)
group by DateBin, Startdt, dt, Lastdt, FullName
, case when t.Name in ('run_parts','run_test') then 'running'
when t.Name = 'unknown' then 'waste'
else t.Name
end
我有一个问题。它 returns 行,一列是状态列,一列是经过时间列。大约有 8 个状态类别。我想将某些状态及其经过的时间总结为 ~3 类。有人知道我该怎么做吗?
这是当前的查询,它按天将条目拆分到 bin 中。
declare @STARDTZ as datetime2
declare @LASTDTZ as datetime2
declare @STARTDT as datetime2
declare @LASTDT as datetime2
set @LASTDT = getdate()
set @STARTDT = DATEADD(dd,-7,getdate())
SET @STARDTZ = DATEADD(dd, DATEDIFF(dd, 0, @STARTDT), 0) --set the start time to 12am (zero) given input datetime
SET @LASTDTZ = DATEADD(dd, DATEDIFF(dd, 0, @LASTDT), 0) --set the stop time to 12am (zero) given input stoptime
;
with dates(dt) as (select @STARDTZ union all select dateadd(day,1,dt) from dates where dt < @LASTDTZ)
select t.Name
,case when t.StartDT>=d.dt then t.StartDT else d.dt end as StartDT
,case when datediff(day,LastDT,dt)=0 then t.LastDT else dateadd(day,1,d.dt) end as LastDT
,datediff(millisecond,case when t.StartDT>=d.dt then t.StartDT else d.dt end
,case when datediff(day,LastDT,dt)=0 then t.LastDT else dateadd(day,1,d.dt) end)/60000.0 as IntervalMin
,t.FullName
,DATEADD(dd, DATEDIFF(dd, 0, dt), 0) as DateBin
from
(
SELECT
CoatingChamberStates.Name as Name
,c.StartDT as StartDT
,c.LastDT as LastDT
,c.IntervalMin
,CoatingChambers.FullName
,DATEADD(dd, DATEDIFF(dd, 0, StartDT), 0) as DateBin
FROM [REO].[dbo].CoatingChamberStateLogs as c
INNER JOIN CoatingChamberStates on c.CoatingChamberStatesID = CoatingChamberStates.CoatingChamberStatesID
INNER JOIN CoatingChambers on c.CoatingChambersID = CoatingChambers.CoatingChambersID
where c.StartDT >= @STARDTZ
and c.LastDT <= @LASTDTZ
) as t
join dates d on d.dt >= cast(t.StartDT as date) and d.dt<=cast(t.LastDT as date)
group by DateBin, StartDT, Name, dt, LastDT, FullName
内容如下returns:
Name StartDT LastDT IntervalMin FullName DateBin
UNKNOWN 2017-04-28 00:05:31.1335380 2017-04-28 11:36:40.1200328 691.1497833 SPECTOR7 2017-04-28 00:00:00.000
UNKNOWN 2017-04-28 00:06:31.6555661 2017-04-28 00:07:31.5121862 0.9976166 LOTUS3 2017-04-28 00:00:00.000
IDLE 2017-04-28 00:07:31.5121862 2017-04-28 11:53:39.7066464 706.1365666 LOTUS3 2017-04-28 00:00:00.000
UNKNOWN 2017-04-28 00:50:32.1654631 2017-04-28 00:51:32.0670071 0.9983666 LOTUS1 2017-04-28 00:00:00.000
RUN_PARTS 2017-04-28 00:51:32.0670071 2017-04-28 00:53:32.0966491 2.0004833 LOTUS1 2017-04-28 00:00:00.000
IDLE 2017-04-28 00:53:32.0966491 2017-04-28 05:50:36.3819295 297.0714166 LOTUS1 2017-04-28 00:00:00.000
RUN_OTHER 2017-04-28 00:53:32.1747858 2017-04-28 12:03:40.0639753 670.1314833 OXFORD2 2017-04-28 00:00:00.000
IDLE 2017-04-28 01:00:32.3043454 2017-04-28 02:26:33.3361640 86.0172000 SPECTOR1 2017-04-28 00:00:00.000
IDLE 2017-04-28 01:50:32.8690160 2017-04-28 07:07:37.3384170 317.0744833 IONTECH 2017-04-28 00:00:00.000
IDLE 2017-04-28 01:57:32.9759673 2017-04-28 02:36:33.6234811 39.0108000 LOTUS8 2017-04-28 00:00:00.000
IDLE 2017-04-28 02:04:33.0037095 2017-04-28 03:10:33.8922959 66.0148166 LOTUS6 2017-04-28 00:00:00.000
UNKNOWN 2017-04-28 02:12:33.2932821 2017-04-28 02:13:33.1640310 0.9978500 SPECTOR6 2017-04-28 00:00:00.000
IDLE 2017-04-28 02:12:33.3089156 2017-04-28 05:27:36.3023807 195.0499000 SPECTOR8 2017-04-28 00:00:00.000
RUN_PARTS 2017-04-28 02:13:33.1640310 2017-04-28 02:31:33.4447516 18.0046666 SPECTOR6 2017-04-28 00:00:00.000
RUN_TEST 2017-04-28 02:26:33.3361640 2017-04-28 03:43:34.4053900 77.0178166 SPECTOR1 2017-04-28 00:00:00.000
IDLE 2017-04-28 02:31:33.4447516 2017-04-28 04:27:35.0346386 116.0265000 SPECTOR6 2017-04-28 00:00:00.000
我想将某些类别的经过时间合并为 3 个类别:"idle"、"running" 和 "waste",例如 "run_parts" 和 "run_test" 将汇总为 "running".
这有意义吗?我该如何处理?谢谢!
您可以使用 case
表达式将名称排序到派生的 table:
with dates(dt) as (select @stardtz union all select dateadd(day,1,dt) from dates where dt < @lastdtz)
select
t.Name
,case when t.Startdt>=d.dt then t.Startdt else d.dt end as Startdt
,case when datediff(day,Lastdt,dt)=0 then t.Lastdt else dateadd(day,1,d.dt) end as Lastdt
,datediff(millisecond,case when t.Startdt>=d.dt then t.Startdt else d.dt end
,case when datediff(day,Lastdt,dt)=0 then t.Lastdt else dateadd(day,1,d.dt) end)/60000.0 as IntervalMin
,t.FullName
,dateadd(day, datediff(day, 0, dt), 0) as DateBin
from (
select
case when CoatingChamberStates.Name in ('run_parts','run_test') then 'running'
when CoatingChamberStates.Name = 'unknown' then 'waste'
else CoatingChamberStates.Name
end as Name
,c.Startdt as Startdt
,c.Lastdt as Lastdt
,c.IntervalMin
,CoatingChambers.FullName
,dateadd(day, datediff(day, 0, Startdt), 0) as DateBin
from [reo].[dbo].CoatingChamberStateLogs as c
inner join CoatingChamberStates
on c.CoatingChamberStatesid = CoatingChamberStates.CoatingChamberStatesid
inner join CoatingChambers
on c.CoatingChambersid = CoatingChambers.CoatingChambersid
where c.Startdt >= @stardtz
and c.Lastdt <= @lastdtz
) as t
join dates d
on d.dt >= cast(t.Startdt as date)
and d.dt<=cast(t.Lastdt as date)
group by DateBin, Startdt, dt, Lastdt, FullName, t.Name
或者您可以 select
和 group by
一个 case
表达式而不是 t.Name
:
with dates(dt) as (select @stardtz union all select dateadd(day,1,dt) from dates where dt < @lastdtz)
select
case when t.Name in ('run_parts','run_test') then 'running'
when t.Name = 'unknown' then 'waste'
else t.Name
end as Name
,case when t.Startdt>=d.dt then t.Startdt else d.dt end as Startdt
,case when datediff(day,Lastdt,dt)=0 then t.Lastdt else dateadd(day,1,d.dt) end as Lastdt
,datediff(millisecond,case when t.Startdt>=d.dt then t.Startdt else d.dt end
,case when datediff(day,Lastdt,dt)=0 then t.Lastdt else dateadd(day,1,d.dt) end)/60000.0 as IntervalMin
,t.FullName
,dateadd(day, datediff(day, 0, dt), 0) as DateBin
from (
select
CoatingChamberStates.Name as Name
,c.Startdt as Startdt
,c.Lastdt as Lastdt
,c.IntervalMin
,CoatingChambers.FullName
,dateadd(day, datediff(day, 0, Startdt), 0) as DateBin
from [reo].[dbo].CoatingChamberStateLogs as c
inner join CoatingChamberStates
on c.CoatingChamberStatesid = CoatingChamberStates.CoatingChamberStatesid
inner join CoatingChambers
on c.CoatingChambersid = CoatingChambers.CoatingChambersid
where c.Startdt >= @stardtz
and c.Lastdt <= @lastdtz
) as t
join dates d
on d.dt >= cast(t.Startdt as date)
and d.dt<=cast(t.Lastdt as date)
group by DateBin, Startdt, dt, Lastdt, FullName
, case when t.Name in ('run_parts','run_test') then 'running'
when t.Name = 'unknown' then 'waste'
else t.Name
end