diff --git a/sql/T_VibrationSensor_Hourly_Report.sql b/sql/T_VibrationSensor_Hourly_Report.sql new file mode 100644 index 0000000..4766659 --- /dev/null +++ b/sql/T_VibrationSensor_Hourly_Report.sql @@ -0,0 +1,238 @@ +/* + 振动传感器振动温度整点报表 + + 说明: + 1. 存储过程 dbo.sp_InsertVibrationSensorHourlyReport 在整点执行时,默认取「上一完整小时」区间内, + 每个 sensor_id 在 T_VibrationSensor_Data 中 collectTime 最晚的一条(并列时取 objId 较大者)。 + 2. reportTime 存该小时起始时间。例如 2025-03-23 09:00:00 表示统计区间 [09:00, 10:00) 的末条数据。 + 3. 定时请使用 SQL Server 代理作业(见脚本末尾示例),不要在应用内写 Quartz 定时任务。 + + 该存储过程无入参: + - 以「当前服务器时间的整点」为区间右端点(不包含),汇总上一小时。 + - 区间为 [DATEADD(hour,-1,@EndExclusive), @EndExclusive)。 +*/ + +IF OBJECT_ID(N'dbo.T_VibrationSensor_Hourly_Report', N'U') IS NULL +BEGIN + CREATE TABLE dbo.T_VibrationSensor_Hourly_Report + ( + objId BIGINT IDENTITY + CONSTRAINT PK_T_VibrationSensor_Hourly_Report PRIMARY KEY, + reportTime DATETIME NOT NULL, + sensor_id NVARCHAR(64) NOT NULL, + collectTime DATETIME NULL, + speed DECIMAL(18, 2) NULL, + displacement DECIMAL(18, 2) NULL, + acceleration DECIMAL(18, 2) NULL, + temperature DECIMAL(18, 2) NULL, + recodeTime DATETIME NOT NULL CONSTRAINT DF_T_VibrationSensor_Hourly_Report_recodeTime DEFAULT GETDATE(), + remark VARCHAR(64) NULL, + CONSTRAINT UQ_T_VibrationSensor_Hourly_Report_hour_sensor UNIQUE (reportTime, sensor_id) + ); + + CREATE NONCLUSTERED INDEX IX_T_VibrationSensor_Hourly_Report_reportTime + ON dbo.T_VibrationSensor_Hourly_Report (reportTime DESC); + + EXEC sp_addextendedproperty N'MS_Description', N'振动传感器整点报表(每小时末条采集)', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report'; + EXEC sp_addextendedproperty N'MS_Description', N'主键', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'objId'; + EXEC sp_addextendedproperty N'MS_Description', N'报表归属小时(该小时起点)', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'reportTime'; + EXEC sp_addextendedproperty N'MS_Description', N'振动传感器ID', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'sensor_id'; + EXEC sp_addextendedproperty N'MS_Description', N'该小时内末条记录的采集时间', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'collectTime'; + EXEC sp_addextendedproperty N'MS_Description', N'速度(mm/s)', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'speed'; + EXEC sp_addextendedproperty N'MS_Description', N'位移(um)', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'displacement'; + EXEC sp_addextendedproperty N'MS_Description', N'加速度(g)', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'acceleration'; + EXEC sp_addextendedproperty N'MS_Description', N'温度(℃)', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'temperature'; + EXEC sp_addextendedproperty N'MS_Description', N'写入报表时间', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'recodeTime'; + EXEC sp_addextendedproperty N'MS_Description', N'备注', N'SCHEMA', N'dbo', N'TABLE', N'T_VibrationSensor_Hourly_Report', N'COLUMN', N'remark'; +END +GO + +IF OBJECT_ID(N'dbo.sp_InsertVibrationSensorHourlyReport', N'P') IS NOT NULL + DROP PROCEDURE dbo.sp_InsertVibrationSensorHourlyReport; +GO + +CREATE PROCEDURE dbo.sp_InsertVibrationSensorHourlyReport +AS +BEGIN + SET NOCOUNT ON; + SET XACT_ABORT ON; + + DECLARE @EndExclusive DATETIME = DATEADD(HOUR, DATEDIFF(HOUR, 0, GETDATE()), 0); + DECLARE @StartInclusive DATETIME = DATEADD(HOUR, -1, @EndExclusive); + DECLARE @ReportTime DATETIME = @StartInclusive; + + ;WITH Ranked AS ( + SELECT d.objId, + d.sensor_id, + d.collectTime, + d.speed, + d.displacement, + d.acceleration, + d.temperature, + d.remark, + ROW_NUMBER() OVER ( + PARTITION BY d.sensor_id + ORDER BY d.collectTime DESC, d.objId DESC + ) AS rn + FROM dbo.T_VibrationSensor_Data d + WHERE d.collectTime >= @StartInclusive + AND d.collectTime < @EndExclusive + ) + INSERT INTO dbo.T_VibrationSensor_Hourly_Report (reportTime, sensor_id, collectTime, speed, displacement, + acceleration, temperature, recodeTime, remark) + SELECT @ReportTime, + r.sensor_id, + @ReportTime, + r.speed, + r.displacement, + r.acceleration, + r.temperature, + @ReportTime, + r.remark + FROM Ranked r + WHERE r.rn = 1 + AND NOT EXISTS ( + SELECT 1 + FROM dbo.T_VibrationSensor_Hourly_Report x + WHERE x.reportTime = @ReportTime + AND x.sensor_id = r.sensor_id + ); + + -- 清理原始明细:删除 recodeTime 三个月前的数据 + DELETE FROM dbo.T_VibrationSensor_Data + WHERE recodeTime < DATEADD(MONTH, -3, @EndExclusive); +END +GO + +IF NOT EXISTS ( + SELECT 1 + FROM sys.extended_properties ep + WHERE ep.class = 1 + AND ep.major_id = OBJECT_ID(N'dbo.sp_InsertVibrationSensorHourlyReport') + AND ep.minor_id = 0 + AND ep.name = N'MS_Description' +) + EXEC sp_addextendedproperty N'MS_Description', + N'按小时汇总振动温度:无入参,固定按当前整点回算上一小时,取各传感器 collectTime 最后一条写入整点报表。', + N'SCHEMA', N'dbo', N'PROCEDURE', N'sp_InsertVibrationSensorHourlyReport'; +ELSE + EXEC sp_updateextendedproperty N'MS_Description', + N'按小时汇总振动温度:无入参,固定按当前整点回算上一小时,取各传感器 collectTime 最后一条写入整点报表。', + N'SCHEMA', N'dbo', N'PROCEDURE', N'sp_InsertVibrationSensorHourlyReport'; +GO + +/* +-------------------------------------------------------------------- +若依菜单与权限(在「菜单管理」中自行添加,或执行类似语句,注意 menu_id / parent_id 勿冲突) + +-- 目录或菜单 C:url = /system/TVibrationSensorHourlyReport +-- perms: system:TVibrationSensorHourlyReport:view / list / export + +INSERT INTO sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, remark) +VALUES (N'振动整点报表', <父菜单ID>, 10, N'/system/TVibrationSensorHourlyReport', N'C', N'0', N'system:TVibrationSensorHourlyReport:view', N'fa fa-table', N'admin', GETDATE(), N''); + +-- 将返回的 menu_id 记入 @mid,再插入按钮权限 F: +-- system:TVibrationSensorHourlyReport:list +-- system:TVibrationSensorHourlyReport:export +-------------------------------------------------------------------- +*/ + +/* +-------------------------------------------------------------------- +SQL Server 代理作业(在 SSMS 中图形化创建,或按需执行以下模板并修改作业名) + +USE msdb; +GO +EXEC dbo.sp_add_job + @job_name = N'振动传感器整点报表', + @enabled = 1, + @description = N'每小时执行 sp_InsertVibrationSensorHourlyReport'; +GO +EXEC dbo.sp_add_jobstep + @job_name = N'振动传感器整点报表', + @step_name = N'写入整点报表', + @subsystem = N'TSQL', + @database_name = N'你的数据库名', + @command = N'EXEC dbo.sp_InsertVibrationSensorHourlyReport;', + @retry_attempts = 2, + @retry_interval = 5; +GO +EXEC dbo.sp_add_schedule + @schedule_name = N'每小时整点', + @freq_type = 4, + @freq_interval = 1, + @freq_subday_type = 8, + @freq_subday_interval = 1, + @active_start_time = 0; +GO +EXEC dbo.sp_attach_schedule + @job_name = N'振动传感器整点报表', + @schedule_name = N'每小时整点'; +GO +EXEC dbo.sp_add_jobserver + @job_name = N'振动传感器整点报表'; +GO + +注意:@active_start_time = 0 表示从 00:00:00 起每 1 小时一次(与 freq_subday 组合为每小时)。 +若环境与版本不同,请用 SSMS「新建作业」→「步骤」执行上述 EXEC →「计划」选「重复执行」每小时、在整点触发更直观。 +-------------------------------------------------------------------- +*/ + +/* +-------------------------------------------------------------------- +振动整点报表随机测试数据(可直接执行) +说明: +1) 生成“今天 00:00 ~ 当前小时前一小时”之间,2 个传感器、每小时 1 条随机整点报表数据。 +2) 已存在同小时同传感器数据会跳过(依赖唯一键 reportTime + sensor_id)。 +-------------------------------------------------------------------- +*/ +DECLARE @TodayStart DATETIME = DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0); +DECLARE @CurrentHour DATETIME = DATEADD(HOUR, DATEDIFF(HOUR, 0, GETDATE()), 0); + +;WITH H AS ( + SELECT @TodayStart AS reportTime + UNION ALL + SELECT DATEADD(HOUR, 1, reportTime) + FROM H + WHERE DATEADD(HOUR, 1, reportTime) < @CurrentHour +), +S AS ( + SELECT N'VS-001' AS sensor_id + UNION ALL + SELECT N'VS-002' +), +R AS ( + SELECT + h.reportTime, + s.sensor_id, + h.reportTime AS collectTime, + CAST((ABS(CHECKSUM(NEWID())) % 1200) / 100.0 AS DECIMAL(18, 2)) AS speed, + CAST((ABS(CHECKSUM(NEWID())) % 5000) / 100.0 AS DECIMAL(18, 2)) AS displacement, + CAST((ABS(CHECKSUM(NEWID())) % 300) / 100.0 AS DECIMAL(18, 2)) AS acceleration, + CAST((ABS(CHECKSUM(NEWID())) % 7000) / 100.0 AS DECIMAL(18, 2)) AS temperature + FROM H h + CROSS JOIN S s +) +INSERT INTO dbo.T_VibrationSensor_Hourly_Report +( + reportTime, sensor_id, collectTime, speed, displacement, acceleration, temperature, recodeTime, remark +) +SELECT + r.reportTime, + r.sensor_id, + r.collectTime, + r.speed, + r.displacement, + r.acceleration, + r.temperature, + r.reportTime, + N'随机测试数据' +FROM R r +WHERE NOT EXISTS ( + SELECT 1 + FROM dbo.T_VibrationSensor_Hourly_Report x + WHERE x.reportTime = r.reportTime + AND x.sensor_id = r.sensor_id +) +OPTION (MAXRECURSION 1000); +GO