如何优化此存储过程?

时间:2018-08-02 15:35:13

标签: sql-server tsql

我下面有存储过程,但有两个问题

  1. 运行非常缓慢,并且
  2. 它返回一个空白结果集

存储过程的想法是进行顺序检查,以查找是否尚未分配任何帐号。

步骤1遍历所有分支并建立tempdetails表。

此后,它将创建已使用的所有号码的列表,并使用该列表删除现有的所有内容,以留下不存在的那些帐号的列表,

但是,尽管我知道缺少帐号,但除了特别长的调整时间之外,它还会返回空白结果集。 任何人都有任何想法出了什么问题吗?

谢谢

ALTER PROCEDURE [dbo].[PracticeFindMissingSequenceDetail]
      @pracId VARCHAR(128),
      @Prefix VARCHAR(256)
AS
BEGIN
    DECLARE @TempDetails TABLE (SequenceCheck VARCHAR(24), 
                                Prefix VARCHAR(4), 
                                BranchName VARCHAR(256), 
                                RisStatus VARCHAR(256), 
                                Rislink VARCHAR(256)
                               );
    DECLARE @Branchlist TABLE (BranchId INTEGER, 
                               BranchName VARCHAR(256), 
                               BranchPrefix VARCHAR(4), 
                               PrefixLength INT, 
                               SequenceLength INT
                              );
    DECLARE @TempPatNo TABLE (Patno VARCHAR(24));

    DECLARE @BranchName  VARCHAR(256),
            @BranchPrefix VARCHAR(256),
            @PrefixLength INT,
            @BranchId INT,
            @SequenceLength INT,
            @rangestart INTEGER,
            @rangeend INTEGER,
            @rangenow INTEGER,
            @startDate DATETIME,
            @Patno VARCHAR(128),
            @FormatZeroes VARCHAR(3),
            @CurrentLength INT,
            @RangeString VARCHAR(256);

    INSERT INTO @Branchlist (BranchId, BranchName, BranchPrefix, PrefixLength, SequenceLength)
        SELECT 
            b.id, b.name, b.prefix, PrefixLength, SequenceLength
        FROM
            Branch b
        INNER JOIN 
            Practice pr ON pr.id = b.practiceid
        INNER JOIN 
            [Sequence] s ON s.id = b.id
        WHERE 
            pr.APIKey = @pracID
            AND b.inactive = 0
            AND b.prefix = @Prefix

        /* insert values for each branch into table*/
        DECLARE BranchPointer CURSOR FOR
            SELECT BranchID FROM @Branchlist

        OPEN BranchPointer

        FETCH NEXT FROM BranchPointer INTO @BranchId

        WHILE @@FETCH_STATUS = 0
        BEGIN
            SELECT @BranchPrefix = (SELECT BranchPrefix 
                                    FROM @Branchlist
                                    WHERE BranchId = @BranchId)
            SELECT @PrefixLength = (SELECT PrefixLength
                                    FROM @Branchlist
                                    WHERE BranchId = @BranchId)
            SELECT @SequenceLength = (SELEct SequenceLength
                                      FROM @Branchlist
                                      WHERE BranchId = @BranchId)

        /* Set the starting date from the sequence */
        SELECT @startDate = (SELECT MIN(MinimumSequenceDate)
                             FROM [Sequence] s
                             WHERE s.id = @BranchId)

        /*get the earliest number in the sequence from the startdate*/                                               
        SELECT @rangestart = (SELECT MIN(SUBSTRING(v.bookingnumber, 3, LEN(bookingnumber))) 
                              FROM Visit v
                              INNER join Branch b ON b.id = v.branchid
                              INNER join Practice pr ON pr.id = b.practiceid
                              WHERE pr.APIKey = @pracId
                                AND LEFT(v.bookingnumber, 2) = @Prefix
                                AND v.date >= @startDate
                                AND v.branchid = @BranchId);

        /*get the latest number in the sequence from the startdate*/
        SELECT @rangeend = (SELECT MAX(SUBSTRING(v.bookingnumber, 3, LEN(bookingnumber))) 
                            FROM Visit v
                            INNER JOIN Branch b ON b.id = v.branchid
                            INNER JOIN Practice pr ON pr.id = b.practiceid
                            WHERE pr.APIKey = @pracId
                              AND LEFT(v.bookingnumber, 2) = @Prefix
                              AND v.date >= @startDate
                              AND v.branchid = @BranchId);

        SET @RangeNow = @rangestart

        WHILE @rangenow < @rangeend
        BEGIN
            /*check if leading zeroes are needed in the number and add them if needed*/
            SET @RangeString = CAST(@RangeNow AS VARCHAR(256))
            SET @CurrentLength = LEN(@rangenow)

            IF @prefixlength + @currentlength < @SequenceLength
                WHILE @CurrentLength + @PrefixLength < @SequenceLength
                BEGIN
                    SET @RangeString = '0' + @RangeString;
                    SET @currentlength = LEN(@RangeString);
                END;

            /*Insert full sequence into temporary table*/
            INSERT INTO @TempDetails (SequenceCheck, Prefix, BranchName)
                SELECT @Prefix + @RangeString, @Prefix, @BranchName

            SET @rangenow =@rangenow+1
        END;

        FETCH NEXT FROM BranchPointer INTO @BranchName
    END

    CLOSE BranchPointer
    DEALLOCATE BranchPointer    

    /*delete existing sequence numbers from table*/
    INSERT INTO @TempPatNo (PatNo)
        SELECT BookingNumber 
        FROM Visit v1 
        INNER JOIN Branch b1 ON b1.id = v1.branchid
        INNER JOIN Practice pr1 ON pr1.id = b1.practiceid
        WHERE pr1.APIKey = @pracId

    DELETE @TempDetails
    WHERE sequencecheck IN (SELECT patNo FROM @TempPatNo)

    /*Insert the status and link for error messages*/
    UPDATE @tempDetails
    SET RisStatus = (SELECT Status 
                     FROM RISErrors r
                     INNER JOIN Practice pr ON pr.id = r.PracticeId
                     WHERE pr.APIKey = @pracId
                       AND VisitNumber = SequenceCheck
                       AND r.id = (SELECT MAX(r1.id) 
                                   FROM RISErrors r1
                                   INNER JOIN Practice pr1 ON pr1.id = r1.PracticeId
                                   WHERE pr1.APIKey = @pracId
                                     AND VisitNumber = SequenceCheck)),
        RisLink = 'http://billing.cryanic.co.za/Clinton/RISErrors?searchquery=' + SequenceCheck

    /*return missing numbers into sequence control callong procedure*/
    SELECT DISTINCT SequenceCheck, RisStatus, Rislink 
    FROM @TempDetails
END

1 个答案:

答案 0 :(得分:0)

阅读您的程序后,我做了一些假设:

  1. 序列 分支
  2. 之间存在一对一的关系
  3. 访问序列
  4. 的详细信息 不需要
  5. BranchName BranchPrefix

我建议不要通过 BranchID 进行查找,而是从游标查询中检索值。不需要表 BranchList ,您可以将光标直接基于查询。另外,可以避免使用 TempPatNo 表。

这是我想出的:

ALTER PROCEDURE [dbo].[PracticeFindMissingSequenceDetail]
  @pracId VARCHAR(128),
  @Prefix VARCHAR(256)
AS
BEGIN
  DECLARE @TempDetails TABLE (
    BranchID INT,
    SequenceCheck VARCHAR(24),
    RisStatus VARCHAR(256),
    Rislink VARCHAR(256)
  );

  DECLARE
    @PrefixLength INT,
    @BranchId INT,
    @SequenceLength INT,
    @rangestart INTEGER,
    @rangeend INTEGER,
    @rangenow INTEGER,
    @startDate DATETIME;

    /* insert values for each branch into table*/
    DECLARE BranchPointer CURSOR FOR
      SELECT b.id, PrefixLength, SequenceLength, s.MinimumSequenceDate
      FROM Branch b
        INNER JOIN Practice pr ON pr.id = b.practiceid
        INNER JOIN [Sequence] s ON s.id = b.id
      WHERE pr.APIKey = @pracID 
        AND b.prefix = @Prefix
        AND b.inactive = 0 

    OPEN BranchPointer
    FETCH NEXT FROM BranchPointer INTO @BranchId, @PrefixLength, @SequenceLength, @startDate

    WHILE @@FETCH_STATUS = 0
    BEGIN

      /*get the earliest and latest number in the sequence from the startdate*/                                               
      SELECT 
        @rangestart = MIN(SUBSTRING(v.bookingnumber, 3, LEN(v.bookingnumber))),
        @rangeend = MAX(SUBSTRING(v.bookingnumber, 3, LEN(v.bookingnumber)))
      FROM Visit v
      WHERE v.branchid = @BranchId
        AND v.date >= @startDate
        AND LEFT(v.bookingnumber, 2) = @Prefix;

      SET @RangeNow = @rangestart

      WHILE @rangenow < @rangeend
      BEGIN

            /*Insert full sequence into temporary table*/
        INSERT INTO @TempDetails (BranchID, SequenceCheck)
          SELECT @BranchId,
            @Prefix + REPLICATE('0', @SequenceLength-@PrefixLength-LEN(@rangenow)) + CAST(@RangeNow AS VARCHAR(256));

        SET @rangenow =@rangenow+1
      END;

      FETCH NEXT FROM BranchPointer INTO @BranchId, @PrefixLength, @SequenceLength, @startDate
    END

    CLOSE BranchPointer
    DEALLOCATE BranchPointer    

    /*delete existing sequence numbers from table*/
    DELETE FROM @TempDetails
    FROM @TempDetails t
      INNER JOIN Visit v ON t.BranchID = v.branchid
    WHERE t.SequenceCheck = v.BookingNumber

    /*Insert the status and link for error messages*/
    UPDATE @tempDetails
    SET RisStatus = (SELECT Status 
                     FROM RISErrors r
                       INNER JOIN Practice pr ON pr.id = r.PracticeId
                     WHERE pr.APIKey = @pracId
                       AND VisitNumber = SequenceCheck
                       AND r.id = (SELECT MAX(r1.id) 
                                   FROM RISErrors r1
                                     INNER JOIN Practice pr1 ON pr1.id = r1.PracticeId
                                   WHERE pr1.APIKey = @pracId
                                     AND VisitNumber = SequenceCheck)),
        RisLink = 'http://billing.cryanic.co.za/Clinton/RISErrors?searchquery=' + SequenceCheck

    /*return missing numbers into sequence control callong procedure*/
    SELECT DISTINCT SequenceCheck, RisStatus, Rislink 
    FROM @TempDetails
END