-- 产品会话管理相关表结构
-- 创建时间: 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 '产品会话管理相关表结构创建完成';
