版本260406

This commit is contained in:
2026-04-06 22:04:05 +08:00
parent 7dc5e73af7
commit 0b150470be
216 changed files with 98993 additions and 33 deletions

View File

@@ -0,0 +1,420 @@
-- 产品会话管理相关表结构
-- 创建时间: 2026-04-01
-- 版本: 1.0
-- =============================================
-- 产品会话表
-- =============================================
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[mdl_production_session]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[mdl_production_session] (
[SessionId] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [DF_mdl_production_session_SessionId] DEFAULT (NEWID()),
[ProductTypeCode] NVARCHAR(50) NOT NULL,
[ProductTypeName] NVARCHAR(200) NOT NULL,
[StationId] NVARCHAR(50) NOT NULL,
[StationName] NVARCHAR(200) NOT NULL,
[OperatorId] NVARCHAR(50) NOT NULL,
[OperatorName] NVARCHAR(100) NOT NULL,
[ShiftId] NVARCHAR(50) NOT NULL,
[ShiftName] NVARCHAR(100) NOT NULL,
[StartedAtUtc] DATETIME2(3) NOT NULL,
[EndedAtUtc] DATETIME2(3) NULL,
[Status] INT NOT NULL CONSTRAINT [DF_mdl_production_session_Status] DEFAULT (0), -- 0=InProgress, 1=CompletedOk, 2=CompletedNg, 3=Cancelled, 4=Paused
[Result] INT NOT NULL CONSTRAINT [DF_mdl_production_session_Result] DEFAULT (0), -- 0=Pending, 1=Ok, 2=Ng
[CurrentLayer] INT NOT NULL CONSTRAINT [DF_mdl_production_session_CurrentLayer] DEFAULT (0),
[TotalLayers] INT NOT NULL CONSTRAINT [DF_mdl_production_session_TotalLayers] DEFAULT (0),
[NgReason] NVARCHAR(500) NULL,
[Remark] NVARCHAR(1000) NULL,
[CreatedAtUtc] DATETIME2(3) NOT NULL CONSTRAINT [DF_mdl_production_session_CreatedAtUtc] DEFAULT (SYSUTCDATETIME()),
[UpdatedAtUtc] DATETIME2(3) NOT NULL CONSTRAINT [DF_mdl_production_session_UpdatedAtUtc] DEFAULT (SYSUTCDATETIME()),
[CreatedBy] NVARCHAR(100) NOT NULL CONSTRAINT [DF_mdl_production_session_CreatedBy] DEFAULT ('System'),
[UpdatedBy] NVARCHAR(100) NOT NULL CONSTRAINT [DF_mdl_production_session_UpdatedBy] DEFAULT ('System'),
CONSTRAINT [PK_mdl_production_session] PRIMARY KEY CLUSTERED ([SessionId] ASC)
);
-- 添加索引
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_StationId_Status] ON [dbo].[mdl_production_session] ([StationId], [Status]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_ProductTypeCode] ON [dbo].[mdl_production_session] ([ProductTypeCode]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_OperatorId] ON [dbo].[mdl_production_session] ([OperatorId]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_ShiftId] ON [dbo].[mdl_production_session] ([ShiftId]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_StartedAtUtc] ON [dbo].[mdl_production_session] ([StartedAtUtc]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_EndedAtUtc] ON [dbo].[mdl_production_session] ([EndedAtUtc]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_Status_Result] ON [dbo].[mdl_production_session] ([Status], [Result]);
PRINT '创建表 mdl_production_session 成功';
END
ELSE
BEGIN
PRINT '表 mdl_production_session 已存在,跳过创建';
END
-- =============================================
-- 产品会话事件表
-- =============================================
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[mdl_production_session_event]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[mdl_production_session_event] (
[EventId] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [DF_mdl_production_session_event_EventId] DEFAULT (NEWID()),
[SessionId] UNIQUEIDENTIFIER NOT NULL,
[EventType] INT NOT NULL, -- 0=SessionCreated, 1=SessionArchived, 2=ProgressUpdated, 3=SessionPaused, 4=SessionResumed, 5=SessionCancelled, 6=LayerStarted, 7=LayerCompleted, 8=NgDetected, 9=ManualIntervention
[Description] NVARCHAR(500) NOT NULL,
[OperatorName] NVARCHAR(100) NOT NULL,
[EventTimeUtc] DATETIME2(3) NOT NULL CONSTRAINT [DF_mdl_production_session_event_EventTimeUtc] DEFAULT (SYSUTCDATETIME()),
[ExtendedProperties] NVARCHAR(MAX) NULL, -- JSON格式的扩展属性
[CreatedAtUtc] DATETIME2(3) NOT NULL CONSTRAINT [DF_mdl_production_session_event_CreatedAtUtc] DEFAULT (SYSUTCDATETIME()),
CONSTRAINT [PK_mdl_production_session_event] PRIMARY KEY CLUSTERED ([EventId] ASC)
);
-- 添加索引
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_event_SessionId] ON [dbo].[mdl_production_session_event] ([SessionId]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_event_EventType] ON [dbo].[mdl_production_session_event] ([EventType]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_event_EventTimeUtc] ON [dbo].[mdl_production_session_event] ([EventTimeUtc]);
-- 添加外键约束
ALTER TABLE [dbo].[mdl_production_session_event] WITH CHECK ADD CONSTRAINT [FK_mdl_production_session_event_mdl_production_session] FOREIGN KEY([SessionId])
REFERENCES [dbo].[mdl_production_session] ([SessionId])
ON DELETE CASCADE;
PRINT '创建表 mdl_production_session_event 成功';
END
ELSE
BEGIN
PRINT '表 mdl_production_session_event 已存在,跳过创建';
END
-- =============================================
-- 产品会话快照表(可选,用于保存会话的详细状态快照)
-- =============================================
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[mdl_production_session_snapshot]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[mdl_production_session_snapshot] (
[SnapshotId] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [DF_mdl_production_session_snapshot_SnapshotId] DEFAULT (NEWID()),
[SessionId] UNIQUEIDENTIFIER NOT NULL,
[LayerNumber] INT NOT NULL,
[SnapshotType] INT NOT NULL, -- 0=LayerStart, 1=LayerEnd, 2=NgDetected, 3=ManualIntervention
[SnapshotData] NVARCHAR(MAX) NOT NULL, -- JSON格式的快照数据
[Images] NVARCHAR(MAX) NULL, -- JSON格式的图片路径列表
[InferenceResults] NVARCHAR(MAX) NULL, -- JSON格式的推理结果
[RuleResults] NVARCHAR(MAX) NULL, -- JSON格式的规则检查结果
[OperatorName] NVARCHAR(100) NULL,
[SnapshotTimeUtc] DATETIME2(3) NOT NULL CONSTRAINT [DF_mdl_production_session_snapshot_SnapshotTimeUtc] DEFAULT (SYSUTCDATETIME()),
[CreatedAtUtc] DATETIME2(3) NOT NULL CONSTRAINT [DF_mdl_production_session_snapshot_CreatedAtUtc] DEFAULT (SYSUTCDATETIME()),
CONSTRAINT [PK_mdl_production_session_snapshot] PRIMARY KEY CLUSTERED ([SnapshotId] ASC)
);
-- 添加索引
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_snapshot_SessionId] ON [dbo].[mdl_production_session_snapshot] ([SessionId]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_snapshot_LayerNumber] ON [dbo].[mdl_production_session_snapshot] ([LayerNumber]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_snapshot_SnapshotType] ON [dbo].[mdl_production_session_snapshot] ([SnapshotType]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_snapshot_SnapshotTimeUtc] ON [dbo].[mdl_production_session_snapshot] ([SnapshotTimeUtc]);
-- 添加外键约束
ALTER TABLE [dbo].[mdl_production_session_snapshot] WITH CHECK ADD CONSTRAINT [FK_mdl_production_session_snapshot_mdl_production_session] FOREIGN KEY([SessionId])
REFERENCES [dbo].[mdl_production_session] ([SessionId])
ON DELETE CASCADE;
PRINT '创建表 mdl_production_session_snapshot 成功';
END
ELSE
BEGIN
PRINT '表 mdl_production_session_snapshot 已存在,跳过创建';
END
-- =============================================
-- 产品会话配置表(可选,用于存储会话相关的配置信息)
-- =============================================
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[mdl_production_session_config]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[mdl_production_session_config] (
[ConfigId] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [DF_mdl_production_session_config_ConfigId] DEFAULT (NEWID()),
[SessionId] UNIQUEIDENTIFIER NOT NULL,
[ConfigType] NVARCHAR(50) NOT NULL, -- 配置类型Camera, Inference, Rules, etc.
[ConfigKey] NVARCHAR(100) NOT NULL,
[ConfigValue] NVARCHAR(MAX) NOT NULL,
[ConfigVersion] NVARCHAR(20) NULL,
[IsActive] BIT NOT NULL CONSTRAINT [DF_mdl_production_session_config_IsActive] DEFAULT (1),
[CreatedAtUtc] DATETIME2(3) NOT NULL CONSTRAINT [DF_mdl_production_session_config_CreatedAtUtc] DEFAULT (SYSUTCDATETIME()),
[UpdatedAtUtc] DATETIME2(3) NOT NULL CONSTRAINT [DF_mdl_production_session_config_UpdatedAtUtc] DEFAULT (SYSUTCDATETIME()),
CONSTRAINT [PK_mdl_production_session_config] PRIMARY KEY CLUSTERED ([ConfigId] ASC)
);
-- 添加索引
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_config_SessionId] ON [dbo].[mdl_production_session_config] ([SessionId]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_config_ConfigType] ON [dbo].[mdl_production_session_config] ([ConfigType]);
CREATE NONCLUSTERED INDEX [IX_mdl_production_session_config_ConfigKey] ON [dbo].[mdl_production_session_config] ([ConfigKey]);
-- 添加外键约束
ALTER TABLE [dbo].[mdl_production_session_config] WITH CHECK ADD CONSTRAINT [FK_mdl_production_session_config_mdl_production_session] FOREIGN KEY([SessionId])
REFERENCES [dbo].[mdl_production_session] ([SessionId])
ON DELETE CASCADE;
PRINT '创建表 mdl_production_session_config 成功';
END
ELSE
BEGIN
PRINT '表 mdl_production_session_config 已存在,跳过创建';
END
-- =============================================
-- 添加表注释
-- =============================================
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[mdl_production_session]') AND type in (N'U'))
BEGIN
EXEC sp_addextendedproperty
@name = N'MS_Description',
@value = N'产品会话表,记录每个产品的装配过程信息',
@level0type = N'SCHEMA', @level0name = N'dbo',
@level1type = N'TABLE', @level1name = N'mdl_production_session';
END
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[mdl_production_session_event]') AND type in (N'U'))
BEGIN
EXEC sp_addextendedproperty
@name = N'MS_Description',
@value = N'产品会话事件表,记录会话过程中的关键事件',
@level0type = N'SCHEMA', @level0name = N'dbo',
@level1type = N'TABLE', @level1name = N'mdl_production_session_event';
END
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[mdl_production_session_snapshot]') AND type in (N'U'))
BEGIN
EXEC sp_addextendedproperty
@name = N'MS_Description',
@value = N'产品会话快照表,保存会话的详细状态快照数据',
@level0type = N'SCHEMA', @level0name = N'dbo',
@level1type = N'TABLE', @level1name = N'mdl_production_session_snapshot';
END
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[mdl_production_session_config]') AND type in (N'U'))
BEGIN
EXEC sp_addextendedproperty
@name = N'MS_Description',
@value = N'产品会话配置表,存储会话相关的配置信息',
@level0type = N'SCHEMA', @level0name = N'dbo',
@level1type = N'TABLE', @level1name = N'mdl_production_session_config';
END
-- =============================================
-- 创建视图:会话统计视图
-- =============================================
IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vw_production_session_statistics]'))
BEGIN
EXEC (N'
CREATE VIEW [dbo].[vw_production_session_statistics] AS
SELECT
s.ProductTypeCode,
s.ProductTypeName,
s.StationId,
s.StationName,
s.OperatorId,
s.OperatorName,
s.ShiftId,
s.ShiftName,
CAST(s.StartedAtUtc AS DATE) AS SessionDate,
COUNT(*) AS TotalSessions,
SUM(CASE WHEN s.Result = 1 THEN 1 ELSE 0 END) AS OkSessions,
SUM(CASE WHEN s.Result = 2 THEN 1 ELSE 0 END) AS NgSessions,
SUM(CASE WHEN s.Status = 0 THEN 1 ELSE 0 END) AS InProgressSessions,
SUM(CASE WHEN s.Status = 3 THEN 1 ELSE 0 END) AS CancelledSessions,
SUM(CASE WHEN s.Status = 4 THEN 1 ELSE 0 END) AS PausedSessions,
CAST(CASE WHEN COUNT(*) > 0 THEN SUM(CASE WHEN s.Result = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) ELSE 0 END AS DECIMAL(5,2)) AS PassRate,
AVG(CASE WHEN s.EndedAtUtc IS NOT NULL THEN DATEDIFF(SECOND, s.StartedAtUtc, s.EndedAtUtc) END) AS AvgProcessingTimeSeconds
FROM [dbo].[mdl_production_session] s
GROUP BY
s.ProductTypeCode, s.ProductTypeName,
s.StationId, s.StationName,
s.OperatorId, s.OperatorName,
s.ShiftId, s.ShiftName,
CAST(s.StartedAtUtc AS DATE)
');
PRINT '创建视图 vw_production_session_statistics 成功';
END
ELSE
BEGIN
PRINT '视图 vw_production_session_statistics 已存在,跳过创建';
END
-- =============================================
-- 创建存储过程:清理过期会话
-- =============================================
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_cleanup_expired_sessions]') AND type in (N'P', N'PC'))
BEGIN
EXEC (N'
CREATE PROCEDURE [dbo].[sp_cleanup_expired_sessions]
@RetentionDays INT = 30,
@CleanedCount INT OUTPUT,
@FreedSpaceBytes BIGINT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @CutoffDate DATETIME2 = DATEADD(DAY, -@RetentionDays, SYSUTCDATETIME());
DECLARE @DeletedCount INT = 0;
-- 计算要删除的会话数量
SELECT @DeletedCount = COUNT(*)
FROM [dbo].[mdl_production_session]
WHERE EndedAtUtc < @CutoffDate;
-- 删除过期会话(级联删除相关事件和快照)
DELETE FROM [dbo].[mdl_production_session]
WHERE EndedAtUtc < @CutoffDate;
-- 返回结果
SET @CleanedCount = @DeletedCount;
SET @FreedSpaceBytes = @DeletedCount * 1024; -- 假设每个会话占用1KB
RETURN 0;
END
');
PRINT '创建存储过程 sp_cleanup_expired_sessions 成功';
END
ELSE
BEGIN
PRINT '存储过程 sp_cleanup_expired_sessions 已存在,跳过创建';
END
-- =============================================
-- 创建存储过程:获取会话统计信息
-- =============================================
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_get_session_statistics]') AND type in (N'P', N'PC'))
BEGIN
EXEC (N'
CREATE PROCEDURE [dbo].[sp_get_session_statistics]
@StartTime DATETIME2,
@EndTime DATETIME2,
@ProductTypeCode NVARCHAR(50) = NULL,
@StationId NVARCHAR(50) = NULL,
@OperatorId NVARCHAR(50) = NULL,
@ShiftId NVARCHAR(50) = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT
COUNT(*) AS TotalSessions,
SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) AS OkSessions,
SUM(CASE WHEN Result = 2 THEN 1 ELSE 0 END) AS NgSessions,
SUM(CASE WHEN Status = 0 THEN 1 ELSE 0 END) AS InProgressSessions,
SUM(CASE WHEN Status = 3 THEN 1 ELSE 0 END) AS CancelledSessions,
SUM(CASE WHEN Status = 4 THEN 1 ELSE 0 END) AS PausedSessions,
CAST(CASE WHEN COUNT(*) > 0 THEN SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) ELSE 0 END AS DECIMAL(5,2)) AS PassRate,
AVG(CASE WHEN EndedAtUtc IS NOT NULL THEN DATEDIFF(SECOND, StartedAtUtc, EndedAtUtc) END) AS AvgProcessingTimeSeconds,
COUNT(*) / NULLIF(SUM(DATEDIFF(HOUR, StartedAtUtc, EndedAtUtc)), 0) AS ThroughputPerHour
FROM [dbo].[mdl_production_session]
WHERE StartedAtUtc >= @StartTime
AND StartedAtUtc <= @EndTime
AND (@ProductTypeCode IS NULL OR ProductTypeCode = @ProductTypeCode)
AND (@StationId IS NULL OR StationId = @StationId)
AND (@OperatorId IS NULL OR OperatorId = @OperatorId)
AND (@ShiftId IS NULL OR ShiftId = @ShiftId);
-- 按产品类型分组统计
SELECT
ProductTypeCode,
ProductTypeName,
COUNT(*) AS TotalSessions,
SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) AS OkSessions,
SUM(CASE WHEN Result = 2 THEN 1 ELSE 0 END) AS NgSessions,
CAST(CASE WHEN COUNT(*) > 0 THEN SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) ELSE 0 END AS DECIMAL(5,2)) AS PassRate
FROM [dbo].[mdl_production_session]
WHERE StartedAtUtc >= @StartTime
AND StartedAtUtc <= @EndTime
AND (@ProductTypeCode IS NULL OR ProductTypeCode = @ProductTypeCode)
AND (@StationId IS NULL OR StationId = @StationId)
AND (@OperatorId IS NULL OR OperatorId = @OperatorId)
AND (@ShiftId IS NULL OR ShiftId = @ShiftId)
GROUP BY ProductTypeCode, ProductTypeName
ORDER BY TotalSessions DESC;
-- 按工位分组统计
SELECT
StationId,
StationName,
COUNT(*) AS TotalSessions,
SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) AS OkSessions,
SUM(CASE WHEN Result = 2 THEN 1 ELSE 0 END) AS NgSessions,
CAST(CASE WHEN COUNT(*) > 0 THEN SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) ELSE 0 END AS DECIMAL(5,2)) AS PassRate,
COUNT(*) / NULLIF(AVG(DATEDIFF(HOUR, StartedAtUtc, EndedAtUtc)), 0) AS ThroughputPerHour
FROM [dbo].[mdl_production_session]
WHERE StartedAtUtc >= @StartTime
AND StartedAtUtc <= @EndTime
AND (@ProductTypeCode IS NULL OR ProductTypeCode = @ProductTypeCode)
AND (@StationId IS NULL OR StationId = @StationId)
AND (@OperatorId IS NULL OR OperatorId = @OperatorId)
AND (@ShiftId IS NULL OR ShiftId = @ShiftId)
AND EndedAtUtc IS NOT NULL
GROUP BY StationId, StationName
ORDER BY TotalSessions DESC;
-- 按操作员分组统计
SELECT
OperatorId,
OperatorName,
COUNT(*) AS TotalSessions,
SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) AS OkSessions,
SUM(CASE WHEN Result = 2 THEN 1 ELSE 0 END) AS NgSessions,
CAST(CASE WHEN COUNT(*) > 0 THEN SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) ELSE 0 END AS DECIMAL(5,2)) AS PassRate,
AVG(DATEDIFF(SECOND, StartedAtUtc, EndedAtUtc)) AS AvgProcessingTimeSeconds
FROM [dbo].[mdl_production_session]
WHERE StartedAtUtc >= @StartTime
AND StartedAtUtc <= @EndTime
AND (@ProductTypeCode IS NULL OR ProductTypeCode = @ProductTypeCode)
AND (@StationId IS NULL OR StationId = @StationId)
AND (@OperatorId IS NULL OR OperatorId = @OperatorId)
AND (@ShiftId IS NULL OR ShiftId = @ShiftId)
AND EndedAtUtc IS NOT NULL
GROUP BY OperatorId, OperatorName
ORDER BY TotalSessions DESC;
-- 按日期分组统计
SELECT
CAST(StartedAtUtc AS DATE) AS SessionDate,
COUNT(*) AS TotalSessions,
SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) AS OkSessions,
SUM(CASE WHEN Result = 2 THEN 1 ELSE 0 END) AS NgSessions,
CAST(CASE WHEN COUNT(*) > 0 THEN SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) ELSE 0 END AS DECIMAL(5,2)) AS PassRate,
COUNT(*) / NULLIF(AVG(DATEDIFF(HOUR, StartedAtUtc, EndedAtUtc)), 0) AS ThroughputPerHour
FROM [dbo].[mdl_production_session]
WHERE StartedAtUtc >= @StartTime
AND StartedAtUtc <= @EndTime
AND (@ProductTypeCode IS NULL OR ProductTypeCode = @ProductTypeCode)
AND (@StationId IS NULL OR StationId = @StationId)
AND (@OperatorId IS NULL OR OperatorId = @OperatorId)
AND (@ShiftId IS NULL OR ShiftId = @ShiftId)
AND EndedAtUtc IS NOT NULL
GROUP BY CAST(StartedAtUtc AS DATE)
ORDER BY SessionDate;
-- 按班次分组统计
SELECT
ShiftId,
ShiftName,
COUNT(*) AS TotalSessions,
SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) AS OkSessions,
SUM(CASE WHEN Result = 2 THEN 1 ELSE 0 END) AS NgSessions,
CAST(CASE WHEN COUNT(*) > 0 THEN SUM(CASE WHEN Result = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) ELSE 0 END AS DECIMAL(5,2)) AS PassRate,
COUNT(*) / NULLIF(AVG(DATEDIFF(HOUR, StartedAtUtc, EndedAtUtc)), 0) AS ThroughputPerHour
FROM [dbo].[mdl_production_session]
WHERE StartedAtUtc >= @StartTime
AND StartedAtUtc <= @EndTime
AND (@ProductTypeCode IS NULL OR ProductTypeCode = @ProductTypeCode)
AND (@StationId IS NULL OR StationId = @StationId)
AND (@OperatorId IS NULL OR OperatorId = @OperatorId)
AND (@ShiftId IS NULL OR ShiftId = @ShiftId)
AND EndedAtUtc IS NOT NULL
GROUP BY ShiftId, ShiftName
ORDER BY TotalSessions DESC;
END
');
PRINT '创建存储过程 sp_get_session_statistics 成功';
END
ELSE
BEGIN
PRINT '存储过程 sp_get_session_statistics 已存在,跳过创建';
END
PRINT '产品会话管理相关表结构创建完成';