Files
OrpaonVision/OrpaonVision.ConfigApp/Infrastructure/Persistence/Database/Schema/CreateProductionSessionTables.sql
2026-04-06 22:04:05 +08:00

421 lines
21 KiB
Transact-SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 产品会话管理相关表结构
-- 创建时间: 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 '产品会话管理相关表结构创建完成';