我使用的是MSSQL 2012。
我有一张名为SensorMeasure的表:
| Id | SensorUnitId| MeasureDate | AlertType | MeasureValue|
| 1 | 3379 | 2016-06-05 00:01:34.000| 1 | 4 |
| 3 | 3381 | 2016-09-18 11:26:33.000| 6 | 5 |
| 4 | 3381 | 2017-03-03 21:46:18.000| 3 | 3 |
| 5 | 3382 | 2016-09-18 11:26:33.000| 5 | 8 |
| 6 | 3381 | 2017-05-03 21:46:18.000| 3 | 0 |
我需要通过SensorUnitId列重复行,然后在通过SensorUnitId进行灌浆后,我需要克隆具有最新日期的行,将AlertType
单元格设置为6并将当前日期和时间设置为MeasureDate
单元格将它们插入表格中。
这是我期望的结果:
| Id | SensorUnitId| MeasureDate | AlertType | MeasureValue|
| 1 | 3379 | 2016-06-05 00:01:34.000| 1 | 4 |
| 3 | 3381 | 2016-09-18 11:26:33.000| 6 | 5 |
| 4 | 3381 | 2017-03-03 21:46:18.000| 4 | 3 |
| 5 | 3382 | 2016-09-18 11:26:33.000| 5 | 8 |
| 6 | 3381 | 2016-11-03 21:46:18.000| 3 | 0 |
| 7 | 3379 | 2016-12-12 15:30:34.000| 6 | 4 |
| 8 | 3381 | 2016-12-12 15:30:34.000| 6 | 0 |
| 9 | 3382 | 2016-12-12 15:30:34.000| 6 | 8 |
这是我如何对行进行分组:
SELECT Max(MeasureDate) as Date, MAX(AlertType) as AlertType,SensorUnitId
FROM SensorsMeasure
GROUP BY SensorUnitId
但我不知道在分组后如何将MeasureDate修改为当前日期和时间以及如何将AlertType设置为6并将这些行插入表中。
更新
正如我已经写过的,我有一个名为SensorMeasure的表。我需要按列SensorUnitId
对表中的所有记录进行分组。
记录分组后,我需要从每个gruop记录中获取最新日期。如果获取的记录的值为AlertType
,我需要过滤它(忽略它),如果记录的值为AlertType
不是6我需要克隆这一行
将AlertType
单元格设置为6,并将当前日期和时间设置为MeasureDate
单元格,并将其插入表格SensorMeasure
。
例如我有这张表:
| Id | SensorUnitId| MeasureDate | AlertType | MeasureValue|
| 1 | 3379 | 2016-06-05 00:01:34.000| 1 | 4 |
| 3 | 3381 | 2016-09-18 11:26:33.000| 6 | 5 |
| 4 | 3381 | 2016-12-03 21:46:18.000| 3 | 3 |
| 5 | 3382 | 2016-09-18 11:26:33.000| 6 | 8 |
所需的表格是:
| Id | SensorUnitId| MeasureDate | AlertType | MeasureValue|
| 1 | 3379 | 2016-06-05 00:01:34.000| 1 | 4 |
| 3 | 3381 | 2016-09-01 11:26:33.000| 6 | 5 |
| 4 | 3381 | 2016-12-03 21:46:18.000| 3 | 3 |
| 5 | 3382 | 2016-09-18 11:26:33.000| 6 | 8 |
| 6 | 3379 | 2016-12-12 21:20:34.000| 6 | 4 |
| 7 | 3381 | 2016-12-12 21:20:34.000| 6 | 3 |
答案 0 :(得分:2)
最新更新
根据我的理解,这是我对问题的重述:
如果每个
MeasureDate
的最新条目(SensorUnitId
)没有AlertType = 6
,我需要在该表中为该SensorUnitId
插入一个新行当前日期,新AlertType
和最新MeasurementValue
。
我认为最简单的方法是使用交叉apply 。
rextester: http://rextester.com/VBP95454
/* testing setup */
create table SensorsMeasure (Id int,SensorUnitId int,MeasureDate datetime,AlertType int,MeasureValue int)
insert into SensorsMeasure (Id,SensorUnitId,MeasureDate,AlertType,MeasureValue) values (1,3379,'2016-06-05 00:01:34.000',1,4),(3,3381,'2016-09-18 11:26:33.000',6,5),(4,3381,'2016-12-03 21:46:18.000',3,3),(5,3382,'2016-09-18 11:26:33.000',6,8)
declare @NewAlertType int ; set @NewAlertType = 6;
declare @ExceptAlertType int; set @ExceptAlertType = 6;
select * from SensorsMeasure;
--**`cross [apply][4]`** version:
--insert into SensorsMeasure (SensorUnitId, MeasureDate, AlertType, MeasureValue)
select distinct
SensorUnitId
, MeasureDate = getdate()
, AlertType = @NewAlertType
, MeasureValue = x.MeasureValue
from SensorsMeasure sm
cross apply (select top 1 MeasureValue, AlertType
from SensorsMeasure i
where i.SensorUnitId = sm.SensorUnitId
order by MeasureDate desc) as x
where x.AlertType != @ExceptAlertType;
您也可以使用 top with ties 执行此操作(在此实例中无需使用交叉或外部应用)。
rextester: http://rextester.com/JWT74538
--insert into SensorsMeasure (SensorUnitId, MeasureDate, AlertType, MeasureValue)
select top 1 with ties
sm.SensorUnitId
, MeasureDate = getdate()
, AlertType = @NewAlertType
, sm.MeasureValue
from SensorsMeasure sm
where sm.AlertType != @ExceptAlertType
order by row_number() over (partition by sm.SensorUnitId order by sm.MeasureDate desc);
上一次更新:
看起来我假设它是基于示例数据的最大警报类型。相反,您可以使用AlertType = 6
。
更新了反映更新的问题:
我需要在
AlertType = 6
之后忽略记录。
我将其解释为忽略SensorUnitIds
AlertType
6
测试代码的rextester链接: http://rextester.com/CLA47054
/* testing setup */
create table SensorsMeasure (Id int,SensorUnitId int,MeasureDate datetime,AlertType int,MeasureValue int)
insert into SensorsMeasure (Id,SensorUnitId,MeasureDate,AlertType,MeasureValue) values (1,3379,'2016-06-05 00:01:34.000',1,4),(3,3381,'2016-09-18 11:26:33.000',6,5),(4,3381,'2017-03-03 21:46:18.000',3,3),(5,3382,'2016-09-18 11:26:33.000',5,8),(6,3381,'2017-05-03 21:46:18.000',3,0);
declare @NewAlertType int; set @NewAlertType = 7;
declare @ExceptAlertType int; set @ExceptAlertType = 6;
--insert into SensorsMeasure (SensorUnitId, MeasureDate, AlertType, MeasureValue)
select
SensorUnitId
, MeasureDate = getdate()
, AlertType = @NewAlertType
, MeasureValue = (select top 1 MeasureValue
from SensorsMeasure i
where i.SensorUnitId = sm.SensorUnitId
order by MeasureDate desc)
from SensorsMeasure sm
where not exists (
select 1
from SensorsMeasure e
where e.SensorUnitId = sm.SensorUnitId
and e.AlertType = @ExceptAlertType
)
group by SensorUnitId;
使用 common table expression 版
;with LatestMeasureValue as (
select
SensorUnitId
, MeasureValue
, rn=row_number() over (partition by SensorUnitId order by MeasureDate desc)
from SensorsMeasure sm
where not exists (
select 1
from SensorsMeasure e
where e.SensorUnitId = sm.SensorUnitId
and e.AlertType = @ExceptAlertType
)
)
--insert into SensorsMeasure (SensorUnitId, MeasureDate, AlertType, MeasureValue)
select
lmv.SensorUnitId
, MeasureDate = getdate()
, AlertType = @NewAlertType
, MeasureValue = lmv.MeasureValue
from LatestMeasureValue lmv
where lmv.rn=1
交叉apply 版本:
--insert into SensorsMeasure (SensorUnitId, MeasureDate, AlertType, MeasureValue)
select distinct
SensorUnitId
, MeasureDate = getdate()
, AlertType = @NewAlertType
, MeasureValue = x.MeasureValue
from SensorsMeasure sm
cross apply (select top 1 MeasureValue
from SensorsMeasure i
where i.SensorUnitId = sm.SensorUnitId
order by MeasureDate desc) as x
where not exists (
select 1
from SensorsMeasure e
where e.SensorUnitId = sm.SensorUnitId
and e.AlertType = @ExceptAlertType
)
<小时/> 老回答:
;with LatestMeasureValue as (
select
SensorUnitId
, MeasureValue
, rn=row_number() over (partition by SensorUnitId order by MeasureDate desc)
from SensorsMeasure
)
insert into SensorsMeasure (SensorUnitId, MeasureDate, AlertType, MeasureValue)
select
lmv.SensorUnitId
, MeasureDate = getdate()
, mat.MaxAlertType
, lmv.MeasureValue
from LatestMeasureValue lmv
cross join (
select
MaxAlertType=max(AlertType)
from SensorsMeasure
) as mat
where lmv.rn=1
这会使用common table expression获取每个MeasureValue
的最新SensorUnitId
,然后交叉加入查询以使max(AlertType)
添加最多AlertType
对于每个最新值,最后使用getdate()
作为新的MeasureDate
你也可以通过其他方式做到这一点。
此方法仅使用子查询和correlated subquery:
insert into SensorsMeasure (SensorUnitId, MeasureDate, AlertType, MeasureValue)
select
SensorUnitId
, MeasureDate = getdate()
, AlertType = (select max(AlertType) from SensorsMeasure)
, MeasureValue = (select top 1 MeasureValue
from SensorsMeasure i
where i.SensorUnitId = sm.SensorUnitId
order by MeasureDate desc)
from SensorsMeasure sm
group by SensorUnitId;
答案 1 :(得分:1)
使用TOP WITH TIES + ROW_NUMBER的另一种方式:
DECLARE @alerttype int = 6
--INSERT INTO SensorMeasure
SELECT top 1 with ties
s.SensorUnitId,
GETDATE() as MeasureDate,
@alerttype as AlertType,
s.MeasureValue
FROM SensorMeasure S
left join (select distinct SensorUnitId from SensorMeasure where AlertType =6) s1
on s1.SensorUnitId = s.SensorUnitId
WHERE s1.SensorUnitId is null
ORDER BY ROW_NUMBER() OVER (PARTITION BY s.SensorUnitId ORDER BY s.MeasureDate DESC)
输出:
SensorUnitId MeasureDate AlertType MeasureValue
------------ ----------------------- ----------- ------------
3379 2016-12-12 17:06:35.953 6 4
3382 2016-12-12 17:06:35.953 6 8
(2 row(s) affected)
修改强>
如果您只需要最新而不是AlertType = 6
,则可以添加一些OUTER APPLY
DECLARE @alerttype int = 6
--INSERT INTO SensorMeasure
SELECT top 1 with ties
s.SensorUnitId,
GETDATE() as MeasureDate,
@alerttype as AlertType,
s.MeasureValue
FROM SensorMeasure S
OUTER APPLY (
SELECT TOP 1 *
FROM SensorMeasure
WHERE SensorUnitId = s.SensorUnitId
ORDER BY MeasureDate DESC
) s1
WHERE s1.AlertType != @alerttype
ORDER BY ROW_NUMBER() OVER (PARTITION BY s.SensorUnitId ORDER BY s.MeasureDate DESC)
输出:
SensorUnitId MeasureDate AlertType MeasureValue
------------ ----------------------- ----------- ------------
3379 2016-12-13 10:05:39.377 6 4
3381 2016-12-13 10:05:39.377 6 3
(2 row(s) affected)