【SQL】大工程:模拟工具故障的时间序列(分平稳期和衰减期)

/********************************

                1、建各种临时表

*********************************/
IF OBJECT_ID('tempdb..#TongsEntity') IS NOT NULL DROP TABLE #TongsEntity;
IF OBJECT_ID('tempdb..#EntityErrorSeries') IS NOT NULL DROP TABLE #EntityErrorSeries;

CREATE TABLE #EntityErrorSeries(--创建实体故障时间表
    Code varchar(10) not null,
    SeqID int not null,
    GEN int not null,
    Times datetime2 not null,
    Event varchar(5) not null,
    ErrorCnt int not null 
    )
    
SELECT ROW_NUMBER() OVER ( ORDER BY ID ) i,* INTO #TongsEntity FROM [TongsEntity];-- 为实体表创建临时表,分配ID以便于枚举

/********************************

    2、程序主要部分:
                [循环嵌套]
                    第一层:枚举实体
                    第二层:产生时间序列

*********************************/

/*
    初始化:定义及赋值各变量
*/

DECLARE @firstdate datetime, @lastdate datetime, @DD int;
DECLARE @Code varchar(10),@SeqID INT,@GEN INT;
DECLARE @ErrorCnt INT;
SELECT @ErrorCnt=COUNT(1) FROM #TongsEntity; --统计#TongsEntity行数
DECLARE @i INT=1; 
DECLARE @rand INT;  --产生随机数
DECLARE @tt INT;
DECLARE @ErrorCount INT;
DECLARE @alpha FLOAT;--故障衰减期的衰减率
/*
    循环主体
*/
SET NOCOUNT ON; --不返回计数[开](提高效率)

WHILE(@i<=@ErrorCnt)--待替换成@ErrorCnt
BEGIN


    SELECT @Code=Code,@SeqID=SeqID,@GEN=GEN FROM #TongsEntity WHERE i=@i;--获取实体的基本信息(代码、序列号)
    --初始化时间起始值
    SELECT @firstdate=(SELECT jbuyoff FROM [GMSAudit].[dbo].[Warehouse] WHERE Code=@Code AND SeqID=@SeqID AND GEN=@GEN);
    
    SELECT @tt=COUNT(*) FROM [GMSAudit].[dbo].[Scrap] WHERE Code=@Code AND SeqID=@SeqID AND GEN=@GEN;--判断是否报废
    
    SELECT @lastdate =(
        CASE @tt
        WHEN 0 THEN '5/23/2020 23:59'--未报废则截止到仿真结束
        WHEN 1 THEN (SELECT ScrapDate FROM [GMSAudit].[dbo].[Scrap] WHERE Code=@Code AND SeqID=@SeqID AND GEN=@GEN)
        END
        );
        
    --嵌套循环
    SET @DD=DATEDIFF(DD,@firstdate,@lastdate)--差别精确到天
    
    WHILE(@DD>=0)
    BEGIN
        SET @ErrorCount= (
            CASE 
            WHEN EXISTS((SELECT * FROM #EntityErrorSeries WHERE Code=@Code AND SeqID=@SeqID AND GEN=@GEN)) 
                THEN ((SELECT MAX(ErrorCnt) FROM #EntityErrorSeries WHERE Code=@Code AND SeqID=@SeqID AND GEN=@GEN))
            ELSE 0 
            END
            )+1;
        IF @ErrorCount>4 SET @alpha=(1-(@ErrorCount-4)*0.0233333); --设置衰减率
        SELECT @rand =
        (
            CASE WHEN @ErrorCount<=4 THEN(
                    CASE (SELECT PMType FROM TongsDefinition T1 WHERE T1.Code = @Code)
                        WHEN 1 THEN ROUND(((35-25)* RAND()+25), 0)
                        WHEN 2 THEN ROUND(((55-45)* RAND()+45), 0)
                        WHEN 3 THEN ROUND(((65-55)* RAND()+55), 0)
                        WHEN 4 THEN ROUND(((75-65)* RAND()+65), 0)
                    END)
            ELSE(
                    CASE (SELECT PMType FROM TongsDefinition T1 WHERE T1.Code = @Code)
                        WHEN 1 THEN (ROUND(((35-25)* RAND()+25), 0)*@alpha)
                        WHEN 2 THEN (ROUND(((55-45)* RAND()+45), 0)*@alpha)
                        WHEN 3 THEN (ROUND(((65-55)* RAND()+55), 0)*@alpha)
                        WHEN 4 THEN (ROUND(((75-65)* RAND()+65), 0)*@alpha)
                    END)
            END
        );

        SET @firstdate=DATEADD(DD,@rand,@firstdate);--完好使用时间1:增加[20,40]天(PM类型为'15天')
        
        SELECT @rand = ROUND(((24-1)* RAND()+1), 0);
        SET @firstdate=DATEADD(HH, @rand, @firstdate);--完好使用时间2:增加[1,24](小时)
        
        --故障申请
        SET @DD=datediff(DD,@firstdate,@lastdate);
        IF @DD<0 BREAK;--当@firstdate增加至大于@lastdate的天数时,DD<0,退出循环
        INSERT INTO #EntityErrorSeries VALUES(@Code,@SeqID,@GEN,@firstdate,'040',@ErrorCount);
        SELECT @rand = ROUND(((24-1)* RAND()+1), 0);
        SET @firstdate=DATEADD(HH, @rand, @firstdate);--审核时间:增加[1,24](小时)
        

        --故障审核
        SET @DD=datediff(DD,@firstdate,@lastdate);
        IF @DD<0 BREAK;
        INSERT INTO #EntityErrorSeries VALUES(@Code,@SeqID,@GEN,@firstdate,'041',@ErrorCount);
        SELECT @rand = ROUND(((4-2)* RAND()+2), 0);
        SET @firstdate=DATEADD(DD,1,@firstdate)--维修时间1:增加[2,4](天)
        SELECT @rand = ROUND(((24-1)* RAND()+1), 0);
        SET @firstdate=DATEADD(HH, @rand, @firstdate);--维修时间2:增加[1,24](小时)
        
      --故障修复完成
        SET @DD=datediff(DD,@firstdate,@lastdate);
        IF @DD<0 BREAK;
        INSERT INTO #EntityErrorSeries VALUES(@Code,@SeqID,@GEN,@firstdate,'042',@ErrorCount);
        
    END
    SET @i=@i+1;
END



SELECT ROW_NUMBER() OVER(ORDER BY Times) AS id, *,  CONVERT(varchar(10),Times, 120 ) AS 日期 
FROM #EntityErrorSeries 
--WHERE Code='EF0798' AND SeqID=1 AND GEN=1
ORDER BY Times ASC


SET NOCOUNT OFF --不返回计数[关]

/********************************

                3、删除临时表

*********************************/
IF OBJECT_ID('tempdb..#TongsEntity') IS NOT NULL DROP TABLE #TongsEntity;
IF OBJECT_ID('tempdb..#EntityErrorSeries') IS NOT NULL DROP TABLE #EntityErrorSeries;

 

posted @ 2020-05-29 19:34  aq_seabiscuit  阅读(203)  评论(0编辑  收藏  举报