Условие If-Else внутри курсора - PullRequest
1 голос
/ 24 января 2011

Мой текущий синтаксис SQL похож на

Declare CursorName CURSOR FOR
 Select Query

Теперь запрос выбора будет содержать условие If-Else.

If @Parameter1 is NULL
 BEGIN
  Select-Query1
 END
ELSE
 BEGIN
  Select-Query2
 END

Как написать вторую инструкцию If-Else внутрикурсор в SQL Server?

помогите пожалуйста!Дайте мне знать для моих входов. !!


Мой оригинальный запрос

Create Table #TempTable(PlanID BIGINT,PlanName NVARCHAR(50),InsuranceCompany Nvarchar(100),CurrentBalance DECIMAL(14,2),
                        [30DaysBalance] DECIMAL(14,2),[60DaysBalance] DECIMAL(14,2),[90DaysBalance] Decimal(14,2),
                        [120DaysBalance] DECIMAL(14,2),[150DaysBalance] Decimal(14,2),CurrentDaysPlanAmount DECIMAL(14,2),
                        [30DaysPlanAmount] DECIMAL(14,2),[60DaysPlanAmount] DECIMAL(14,2),[90DaysPlanAmount] Decimal(14,2),
                        [120DaysPlanAmount] DECIMAL(14,2),[150DaysPlanAmount] Decimal(14,2),StartDate DateTime,EndDate DateTime
                       )

НАЧАТЬ

    Declare @BillID BIGINT,@PatientID BIGINT,@BillDetailID BIGINT,@SendDt DateTime

    Declare Cursor_Claim_PlanAgingReport Cursor 

    For Select Bill.BillID,Bill.PatientID,BillDetail.BillDetailID,Claim.SendDt From Bill Inner Join
        BillDetail On Bill.BillID = BillDetail.BillID Inner Join
        Claim on Bill.BillID = Claim.BillID Left Outer Join
        Payment On Bill.BillID = Payment.BillID 
        Where 
        ---Payment.BillID Is Null  AND
        Claim.SendDt 
        Between @StartDt AND @EndDt 
        ---And Claim.Status = 'Sent' 
        AND Claim.Status = 'Resent'



    Open Cursor_Claim_PlanAgingReport

    FETCH NEXT FROM Cursor_Claim_PlanAgingReport INTO @BillID,@PatientID,@BillDetailID,@SendDt

    While @@FETCH_STATUS = 0
    BEGIN

        Insert Into #TempTable SELECT Distinct(vwAgingPlan.PlanID),vwAgingPlan.Plan_Name,vwAgingPlan.Insurance_Company,         

        --// Current Balance --
        IsNull((SELECT top 1 vwAgingPlan.Copay as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) < 30 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID), 0) AS CurrentBalance,

        --// [30DaysBalance] --
        IsNull((SELECT top 1 vwAgingPlan.Copay as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) > 30 AND DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) <= 60 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID), 0) AS [30DaysBalance],

        --// [60DaysBalance] --
        IsNull((SELECT top 1 vwAgingPlan.Copay as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) > 60 AND DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) <= 90 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID), 0) AS [60DaysBalance],

        --// [90DaysBalance] --
        IsNull(
            (SELECT  top 1vwAgingPlan.Copay as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) > 90 AND DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) <= 120 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID), 0) AS [90DaysBalance],

        --// [120DaysBalance] --
        IsNull((SELECT top 1 vwAgingPlan.Copay as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) > 120 AND DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) <= 150 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID), 0) AS [120DaysBalance],

        --// [150DaysBalance] --
        IsNull((SELECT top 1 vwAgingPlan.Copay as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.SendDt,getDate()) > 150 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID), 0) AS [150DaysBalance],

        IsNull((SELECT top 1 vwAgingPlan.PlanAmount as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.CreatedDt,getdate()) <= 30 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID),0) AS CurrentDaysPlanAmount,
        IsNull((SELECT top 1 vwAgingPlan.PlanAmount as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.CreatedDt, getdate()) > 30 AND DATEDIFF("dd", vwAgingPlan.CreatedDt,getdate()) <= 60 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID),0) AS [30DaysPlanAmount],
        IsNull((SELECT top 1 vwAgingPlan.PlanAmount as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.CreatedDt, getdate()) > 60 AND DATEDIFF("dd", vwAgingPlan.CreatedDt,getdate()) <= 90 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID),0) AS [60DaysPlanAmount],
        IsNull((SELECT top 1 vwAgingPlan.PlanAmount as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.CreatedDt, getdate()) > 90 AND DATEDIFF("dd", vwAgingPlan.CreatedDt,getdate()) <= 120 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID),0) AS [90DaysPlanAmount],
        IsNull((SELECT top 1 vwAgingPlan.PlanAmount as s from vwAgingPlan WHERE DATEDIFF("dd", vwAgingPlan.CreatedDt, getdate()) > 120 AND DATEDIFF("dd", vwAgingPlan.CreatedDt,getdate()) <= 150 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID),0) AS [120DaysPlanAmount],
        IsNull((SELECT top 1 vwAgingPlan.PlanAmount as s from vwAgingPlan WHERE DATEDIFF("dd",  vwAgingPlan.CreatedDt, getdate()) > 150 And vwAgingPlan.BillID = @BillID And vwAgingPlan.PatientID = @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID), 0) AS [150DaysPlanAmount] ,
        @StartDt,@EndDt
    FROM 
        vwAgingPlan
    WHERE
        vwAgingPlan.BillID = @BillID AND vwAgingPlan.PatientID= @PatientID AND vwAgingPlan.BillDetailID = @BillDetailID

    FETCH NEXT FROM Cursor_Claim_PlanAgingReport INTO @BillID,@PatientID,@BillDetailID,@SendDt
END


Close Cursor_Claim_PlanAgingReport
Deallocate Cursor_Claim_PlanAgingReport

Select * From #TempTable    

END

Мой запрос If-Else

IF @InsuranceName IS NULL


BEGIN
      SELECT Bill.BillID,
             Bill.PatientID,
             BillDetail.BillDetailID,
             Claim.SendDt,
             Claim.SendDT,
             InsurancePlan.Name
      FROM   Bill
             INNER JOIN BillDetail
               ON Bill.BillID = BillDetail.BillID
             INNER JOIN Claim
               ON Bill.BillID = Claim.BillID
             INNER JOIN Payment
               ON Bill.BillID = Payment.BillID
             INNER JOIN dbo.InsurancePlan
               ON dbo.BillDetail.PlanID = dbo.InsurancePlan.InsurancePlanID
             INNER JOIN dbo.InsuranceCompany
               ON dbo.InsurancePlan.InsuranceCompID = dbo.InsuranceCompany.InsuranceCompID
      WHERE   
        Claim.SendDt BETWEEN @StartDt AND @EndDt
          AND Claim.Status = 'Resent'
             --OR Claim.Status = 'Resent'

      PRINT 'No Insurance Name'
  END
ELSE
  BEGIN
      SELECT Bill.BillID,
             Bill.PatientID,
             BillDetail.BillDetailID,
             Claim.SendDt,
             Claim.SendDT,
             Claim.[Status],
             Payment.BillId AS PaymentBillID,
             InsurancePlan.Name
      FROM   Bill
             INNER JOIN BillDetail
               ON Bill.BillID = BillDetail.BillID
             INNER JOIN Claim
               ON Bill.BillID = Claim.BillID
             INNER JOIN Payment
               ON Bill.BillID = Payment.BillID
             INNER JOIN dbo.InsurancePlan
               ON dbo.BillDetail.PlanID = dbo.InsurancePlan.InsurancePlanID
             INNER JOIN dbo.InsuranceCompany
               ON dbo.InsurancePlan.InsuranceCompID = dbo.InsuranceCompany.InsuranceCompID
      WHERE  InsurancePlan.Name = @InsuranceName
             --AND Payment.BillID IS NULL
             AND Claim.SendDt BETWEEN @StartDt AND @EndDt
             AND Claim.[Status]='Resent'  

      PRINT 'Insurance Name: ' + @InsuranceName
  END 

Ответы [ 2 ]

11 голосов
/ 24 января 2011

столько, сколько я HATE курсоры, попробуйте это:

DECLARE @FetchColumn varchar(10)

If @Parameter1 is NULL

BEGIN
    DECLARE YourCursor CURSOR FOR
        SELECT
            Column1
        FROM YourTable
        WHERE ...
        FOR READ ONLY
END
ELSE
BEGIN
    DECLARE YourCursor CURSOR FOR
        SELECT
            ColumnB
        FROM YourTable
        WHERE ...
        FOR READ ONLY
END
--populate and allocate resources to the cursor
OPEN YourCursor

--process each row
WHILE 1=1
BEGIN

    FETCH NEXT FROM YourCursor
        INTO @FetchColumn 

    --finished fetching all rows?
    IF @@FETCH_STATUS <> 0
    BEGIN --YES, all done fetching
        --exith the loop
        BREAK
    END --IF finished fetching

    --do something here--
    --do something here--
    PRINT @FetchColumn 

END --WHILE

--close and free the cursor's resources
CLOSE YourCursor
DEALLOCATE YourCursor

Из вашего кода похоже, что у вас есть условия динамического поиска. Ключ к условиям динамического поиска заключается в том, чтобы убедиться, что используется индекс, а не то, как я могу легко повторно использовать код, устранить дублирования в запросе или попытаться сделать все с одним и тем же запросом. Вот очень полная статья о том, как справиться с этой темой:

Условия динамического поиска в T-SQL Эрланда Соммарского

Он охватывает все проблемы и методы попыток написания запросов с несколькими необязательными условиями поиска. Это главное, что вам нужно беспокоиться, это не дублирование кода, а использование индекса. Если ваш запрос не может использовать индекс, он будет плохо сформирован. Существует несколько методов, которые могут использоваться или не разрешать использование индекса.

вот оглавление:

  Introduction
      The Case Study: Searching Orders
      The Northgale Database
   Dynamic SQL
      Introduction
      Using sp_executesql
      Using the CLR
      Using EXEC()
      When Caching Is Not Really What You Want
   Static SQL
      Introduction
      x = @x OR @x IS NULL
      Using IF statements
      Umachandar's Bag of Tricks
      Using Temp Tables
      x = @x AND @x IS NOT NULL
      Handling Complex Conditions
   Hybrid Solutions – Using both Static and Dynamic SQL
      Using Views
      Using Inline Table Functions
   Conclusion
   Feedback and Acknowledgements
   Revision History

если вы работаете с верной версией SQL Server 2008, можно использовать дополнительную технику, см .: Условия динамического поиска в версии T-SQL для SQL 2008 (SP1 CU5 и более поздние версии)

Если вы используете правильную версию SQL Server 2008, вы можете просто добавить OPTION (RECOMPILE) к запросу, и значение локальной переменной во время выполнения используется для оптимизации.

Учтите, что OPTION (RECOMPILE) примет этот код (где индекс не может использоваться с этим беспорядком OR с):

WHERE
    (@search1 IS NULL or Column1=@Search1)
    AND (@search2 IS NULL or Column2=@Search2)
    AND (@search3 IS NULL or Column3=@Search3)

и оптимизировать его во время выполнения (при условии, что только @ Search2 был передан со значением):

WHERE
    Column2=@Search2

и индекс можно использовать (если он определен в столбце 2)

0 голосов
/ 24 января 2011

Я бы изменил основной SELECT для курсора так, чтобы он использовал оператор CASE вместе с табличной переменной, чтобы установить поле char, которое будет отмечать каждую запись как определенный тип.

Например, что-то вроде:

DECLARE @Stuff TABLE
(
    ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
    SystemID int,
    Flag char
)


INSERT INTO @Stuff (SystemID, Flag)
SELECT 
    SystemID,

    CASE SomeFieldInMainTable
        WHEN 1 THEN 'A'
        WHEN 2 THEN 'B'
        WHEN 3 THEN 'C'
        ELSE 0
    END

FROM TheTable

Это позволит вам создать подмножество любой таблицы, которую вы используете для перемещения курсора, и "пометить" записи в этом подмножестве на основе логики CASE, подходящей для ваших подзапросов, но вынужно только поразить основную таблицу одним большим SELECT, а не отдельными в блоках IF.

После заполнения табличной переменной вы можете запросить ее отдельно, чтобы получить необходимые данные, извлеченные из основной таблицы.

...