SQL - 我的查询需要一个小时的游标(太长)

SQL - Cursors taking an hour for my query (too long)

我将要 post 代码,但我首先要解释我试图通过伪代码完成的任务。

我正在临时 table 中插入重复的记录。然后我想单独检查 table 中的每条记录以执行匹配该记录的 select 并基于此,为所有记录标记一个字段最终('Y','N', 'E').为了实现这一点,我使用了 2 个游标,这很糟糕。这很糟糕,因为它有很多难以阅读、令人讨厌的代码,而且它还使我的查询需要一个多小时才能达到 运行。 运行 selects/updates 有没有更好的方法?

代码如下:

declare @hic [nvarchar](255)
declare @oscar [float] 
declare @typecode [float] 
declare @fromdate [datetime] 
declare @thrudate [datetime] 
declare @claimcode [float] 
declare @claimeffdate [datetime] 

declare @id [int]
declare @finalhic [nvarchar](255)
declare @finaloscar [float] 
declare @finaltypecode [float] 
declare @finalfromdate [datetime] 
declare @finalthrudate [datetime] 
declare @finalclaimcode [float] 
declare @finalclaimeffdate [datetime]

declare cur1 CURSOR LOCAL for
select   
     [HIC #], 
     [Provider Oscar #],
     [Claim Type Code], 
     [Claim From Date], 
     [Claim Thru Date],
     [Claim Adjustment Type Code]  from #tmp_hic_cancels

open cur1
fetch next from cur1 into @hic, @oscar, @typecode, @fromdate, @thrudate,     @claimcode
while @@FETCH_STATUS = 0 BEGIN

--select @hic, @oscar, @typecode, @fromdate, @thrudate, @claimcode
begin

--typecode = 10
if @typecode = 10
BEGIN
    insert into  #tmp_hic_cancel_batch
    select 
        [ID],
    [HIC #], 
    [Provider Oscar #], 
    [Claim Type Code],
    [Claim From Date], 
    [Claim Thru Date],
    [Claim Adjustment Type Code],
    [Claim Effective Date]
    from [ACO].[dbo].['PA_Header_Temp']
    where [HIC #] = @hic
    and  [Claim Type Code] = @typecode
        and [Provider Oscar #] = @oscar
        and [Claim From Date] = @fromdate 


    --Mark final based on claimcode
    DECLARE Cur2 CURSOR FOR
     select 
     [ID],
    [HIC #], 
    [Provider Oscar #], 
    [Claim Type Code],
    [Claim From Date], 
    [Claim Thru Date],
    [Claim Adjustment Type Code],
    [Claim Effective Date]
         from #tmp_hic_cancel_batch
    OPEN Cur2;
    FETCH NEXT FROM Cur2 INTO @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate;
    WHILE @@FETCH_STATUS = 0
    --BEGIN CUR2
    BEGIN
    --IF A 2 EXISTS IN BATCH, perform these operations
        if (EXISTS (select 
            [Claim Adjustment Type Code] 
        from [ACO].[dbo].['PA_Header_Temp']
        where [HIC #] = @finalhic
            and [Provider Oscar #] = @finaloscar
            and [Claim Type Code] = @finaltypecode
            and [Claim From Date] = @finalfromdate
            and [Claim Adjustment Type Code] = @finalclaimcode
            and [Claim Adjustment Type Code]  = 2))
        BEGIN
        --MARK FINAL CODES BASED ON CLAIM CODES
            if @finalclaimcode = 2
            begin
                    insert into #tmp_hic_final
                    select @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
                    , 'Y', DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
            end
            else
            begin
                    insert into #tmp_hic_final
                    select @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
                    ,'N', DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
            end
        END
        --IF NO 2 EXISTS IN BATCH
        ELSE
        BEGIN
            if @finalclaimcode = 1
            begin
                    insert into #tmp_hic_final
                    select @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
                    ,'N', DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
            end
        END 
        --END IF NO 2 EXISTS IN BATCH

        FETCH NEXT FROM Cur2 INTO @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
    END;
    --END CUR2
    CLOSE Cur2;
    DEALLOCATE Cur2;

END--END typecode = 10

--else typecode = 40...
else
BEGIN
    insert into #tmp_hic_cancel_batch
    select 
        [ID],
    [HIC #], 
    [Provider Oscar #], 
    [Claim Type Code],
    [Claim From Date], 
    [Claim Thru Date],
    [Claim Adjustment Type Code],
    [Claim Effective Date]
    from [ACO].[dbo].['PA_Header_Temp']
    where [HIC #] = @hic
    and [Provider Oscar #] = @oscar
    and [Claim Type Code] = @typecode
    and [Claim From Date] = @fromdate 
    and [Claim Thru Date] = @thrudate
    and [Claim Adjustment Type Code] = @claimcode

--Mark final based on claimcode
    DECLARE Cur2 CURSOR FOR
     select
     [ID],
    [HIC #], 
    [Provider Oscar #], 
    [Claim Type Code],
    [Claim From Date], 
    [Claim Thru Date],
    [Claim Adjustment Type Code],
    [Claim Effective Date]
         from #tmp_hic_cancel_batch
    OPEN Cur2;
    FETCH NEXT FROM Cur2 INTO @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
    WHILE @@FETCH_STATUS = 0
    --BEGIN CUR2
    BEGIN
    --IF A 2 EXISTS IN BATCH, perform these operations
        if (EXISTS (select 
            [Claim Adjustment Type Code] 
        from [ACO].[dbo].['PA_Header_Temp']
        where [HIC #] = @finalhic
            and [Claim Type Code] = @finaltypecode
            and [Provider Oscar #] = @finaloscar
            and [Claim From Date] = @finalfromdate
            and [Claim Thru Date] = @finalthrudate
            and [Claim Adjustment Type Code] = @finalclaimcode
            and [Claim Adjustment Type Code]  = 2))
        BEGIN
        --MARK FINAL CODES BASED ON CLAIM CODES
            if @finalclaimcode = 2
            begin
                    insert into #tmp_hic_final
                    select @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
                    ,'Y', DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
            end
            else
            begin
                    insert into #tmp_hic_final
                    select @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
                    ,'N', DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
            end
        END
        --IF NO 2 EXISTS IN BATCH
        ELSE
        BEGIN
            if @finalclaimcode = 1
            begin
                    insert into #tmp_hic_final
                    select @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
                    ,'N', DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
            end
            else
            begin
                    insert into #tmp_hic_final
                    select @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
                    ,'Y', DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
            end
        END 
        --END IF NO 2 EXISTS IN BATCH

        FETCH NEXT FROM Cur2 INTO @id, @finalhic, @finaloscar, @finaltypecode, @finalfromdate, @finalthrudate, @finalclaimcode, @finalclaimeffdate
    END;
    --END CUR2
    CLOSE Cur2;
    DEALLOCATE Cur2;

END

    --clears temp table for next batch
    delete from #tmp_hic_cancel_batch

fetch next from cur1 into @hic, @oscar, @typecode, @fromdate, @thrudate, @claimcode
END

close cur1
deallocate cur1

正如您所猜测的那样,游标正是问题所在。它们效率极低,只适用于非常有限的条件。对于大规模处理,就像这样,即使是嵌套操作,游标也不是一个好的解决方案。

您将需要完成整个过程并从游标中提取出每一位。我会给你第一个,这就是为什么我认为这是一个答案而不仅仅是评论。

发生在第一个游标内的第一个插入可以提取到整个过程开始之前,它最终看起来像这样:

insert into  #tmp_hic_cancel_batch                     
select PAHT.[ID],
        PAHT.[HIC #], 
        PAHT.[Provider Oscar #], 
        PAHT.[Claim Type Code],
        PAHT.[Claim From Date], 
        PAHT.[Claim Thru Date],
        PAHT.[Claim Adjustment Type Code],
        PAHT.[Claim Effective Date],
        PAHT.[Current ClaimID],
        PAHT.[Claim Bill Facility Type Code],
        PAHT.[Claim Bill Classification Code],
        PAHT.[Principal Diagnosis Code],
        PAHT.[Admitting Diagnosis Code],
        PAHT.[Claim Medicare Non Payment Reason Code],
        PAHT.[Claim Payment Amount],
        PAHT.[Claim NCH Primary Payer Code],
        PAHT.[FIPS state Code],
        PAHT.[Bene Patient Status Code],
        PAHT.[Diagnosis Related Group Code],
        PAHT.[Claim Outpatient Service Type Code],
        PAHT.[Facility Provider NPI #],
        PAHT.[Operating Provider NPI #],
        PAHT.[Attending provider NPI #],
        PAHT.[Other Provider NPI #],
        PAHT.[Claim IDR Load Date],
        PAHT.[Bene Equitable BIC HICN #],
        PAHT.[Claim Admission Type Code],
        PAHT.[Claim Admission Source Code],
        PAHT.[Claim Bill Frequency Code],
        PAHT.[Claim Query Code],
from [ACO].[dbo].['PA_Header_Temp'] PAHT
        inner join #tmp_hic_cancels THC on PAHT.[HIC #] = THC.[HIC #] and
                                        PAHT.[Claim Type Code] = THC.[Claim Type Code] and 
                                        PAHT.[Provider Oscar #] = THC.[Provider Oscar #] and
                                        PAHT.[Claim From Date] = THC.[Claim From Date] 
where PAHT.[Claim Type Code] = 10

然后您将不得不移动到下一个游标内的下一个位,并以相同的方式提取它,将游标操作更改为选择与适当连接的组合。

您可能会发现整个事情减少为几个查询。或者,如果对问题的具体情况了解足够多,就可以直接提出这些问题。但是整个过程需要几个小时,所以我不会尝试整个过程。另外,我很确定上面的是正确的,但是我没有办法测试它,所以...

是的,这可以变得更快、更高效。这可以通过查询(选择、插入、更新)和无游标来完成。但是你不可能让某人免费为你做所有事情。

使用@Gilchrist 代码作为基础,这就是我用来将我的代码表单光标修复为 4 个实际 sql 插入到选择... 它检查 typecode = 20 和 2 是否存在,然后是 typecode = 20 而不是 2。 第二组是 typecode <> 20 并且存在 2,然后是 typecode <> 20 而不是 2。

希望有一天有人能发现这个有用的东西:

insert into  #tmp_hic_final                     
select distinct PAHT.[ID],
    PAHT.[HIC #], 
    PAHT.[Provider Oscar #], 
    PAHT.[Claim Type Code],
    PAHT.[Claim From Date], 
    PAHT.[Claim Thru Date],
    PAHT.[Claim Adjustment Type Code],
    PAHT.[Claim Effective Date],
    PAHT.[Current ClaimID],
    PAHT.[Claim Bill Facility Type Code],
    PAHT.[Claim Bill Classification Code],
    PAHT.[Principal Diagnosis Code],
    PAHT.[Admitting Diagnosis Code],
    PAHT.[Claim Medicare Non Payment Reason Code],
    PAHT.[Claim Payment Amount],
    PAHT.[Claim NCH Primary Payer Code],
    PAHT.[FIPS state Code],
    PAHT.[Bene Patient Status Code],
    PAHT.[Diagnosis Related Group Code],
    PAHT.[Claim Outpatient Service Type Code],
    PAHT.[Facility Provider NPI #],
    PAHT.[Operating Provider NPI #],
    PAHT.[Attending provider NPI #],
    PAHT.[Other Provider NPI #],
    PAHT.[Claim IDR Load Date],
    PAHT.[Bene Equitable BIC HICN #],
    PAHT.[Claim Admission Type Code],
    PAHT.[Claim Admission Source Code],
    PAHT.[Claim Bill Frequency Code],
    PAHT.[Claim Query Code],
    CASE 
        WHEN PAHT.[Claim Adjustment Type Code] = '2' THEN 'Y'
        ELSE 'N' 
    END,
    DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
from [ACO].[dbo].['PA_Header_Temp'] PAHT
    inner join #tmp_hic_cancels THC on PAHT.[HIC #] = THC.[HIC #] and
                                    PAHT.[Claim Type Code] = THC.[Claim Type Code] and 
                                    PAHT.[Provider Oscar #] = THC.[Provider Oscar #] and
                                    PAHT.[Claim From Date] = THC.[Claim From Date] and
                                    PAHT.[Claim Adjustment Type Code] = THC.[Claim Adjustment Type Code]
where PAHT.[Claim Type Code] = 10
    and EXISTS (select 
                [Claim Adjustment Type Code] 
            from [ACO].[dbo].['PA_Header_Temp']
            where 
                [HIC #] = PAHT.[HIC #]
                and [Provider Oscar #] = PAHT.[Provider Oscar #]
                and [Claim Type Code] = PAHT.[Claim Type Code]
                and [Claim From Date] = PAHT.[Claim From Date]
                and [Claim Adjustment Type Code] = PAHT.[Claim Adjustment Type Code]
                and [Claim Adjustment Type Code]  = 2)

insert into  #tmp_hic_final  
select distinct PAHT.[ID],
    PAHT.[HIC #], 
    PAHT.[Provider Oscar #], 
    PAHT.[Claim Type Code],
    PAHT.[Claim From Date], 
    PAHT.[Claim Thru Date],
    PAHT.[Claim Adjustment Type Code],
    PAHT.[Claim Effective Date],
    PAHT.[Current ClaimID],
    PAHT.[Claim Bill Facility Type Code],
    PAHT.[Claim Bill Classification Code],
    PAHT.[Principal Diagnosis Code],
    PAHT.[Admitting Diagnosis Code],
    PAHT.[Claim Medicare Non Payment Reason Code],
    PAHT.[Claim Payment Amount],
    PAHT.[Claim NCH Primary Payer Code],
    PAHT.[FIPS state Code],
    PAHT.[Bene Patient Status Code],
    PAHT.[Diagnosis Related Group Code],
    PAHT.[Claim Outpatient Service Type Code],
    PAHT.[Facility Provider NPI #],
    PAHT.[Operating Provider NPI #],
    PAHT.[Attending provider NPI #],
    PAHT.[Other Provider NPI #],
    PAHT.[Claim IDR Load Date],
    PAHT.[Bene Equitable BIC HICN #],
    PAHT.[Claim Admission Type Code],
    PAHT.[Claim Admission Source Code],
    PAHT.[Claim Bill Frequency Code],
    PAHT.[Claim Query Code],
    'N',
    DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
from [ACO].[dbo].['PA_Header_Temp'] PAHT
    inner join #tmp_hic_cancels THC on PAHT.[HIC #] = THC.[HIC #] and
                                    PAHT.[Claim Type Code] = THC.[Claim Type Code] and 
                                    PAHT.[Provider Oscar #] = THC.[Provider Oscar #] and
                                    PAHT.[Claim From Date] = THC.[Claim From Date]  and
                                    PAHT.[Claim Adjustment Type Code] = THC.[Claim Adjustment Type Code]
where PAHT.[Claim Type Code] = 10
    and EXISTS (select 
                [Claim Adjustment Type Code] 
            from [ACO].[dbo].['PA_Header_Temp']
            where 
                [HIC #] = PAHT.[HIC #]
                and [Provider Oscar #] = PAHT.[Provider Oscar #]
                and [Claim Type Code] = PAHT.[Claim Type Code]
                and [Claim From Date] = PAHT.[Claim From Date]
                and [Claim Adjustment Type Code] = PAHT.[Claim Adjustment Type Code]
                and [Claim Adjustment Type Code]  <> 2)

insert into  #tmp_hic_final  
select distinct PAHT.[ID],
    PAHT.[HIC #], 
    PAHT.[Provider Oscar #], 
    PAHT.[Claim Type Code],
    PAHT.[Claim From Date], 
    PAHT.[Claim Thru Date],
    PAHT.[Claim Adjustment Type Code],
    PAHT.[Claim Effective Date],
    PAHT.[Current ClaimID],
    PAHT.[Claim Bill Facility Type Code],
    PAHT.[Claim Bill Classification Code],
    PAHT.[Principal Diagnosis Code],
    PAHT.[Admitting Diagnosis Code],
    PAHT.[Claim Medicare Non Payment Reason Code],
    PAHT.[Claim Payment Amount],
    PAHT.[Claim NCH Primary Payer Code],
    PAHT.[FIPS state Code],
    PAHT.[Bene Patient Status Code],
    PAHT.[Diagnosis Related Group Code],
    PAHT.[Claim Outpatient Service Type Code],
    PAHT.[Facility Provider NPI #],
    PAHT.[Operating Provider NPI #],
    PAHT.[Attending provider NPI #],
    PAHT.[Other Provider NPI #],
    PAHT.[Claim IDR Load Date],
    PAHT.[Bene Equitable BIC HICN #],
    PAHT.[Claim Admission Type Code],
    PAHT.[Claim Admission Source Code],
    PAHT.[Claim Bill Frequency Code],
    PAHT.[Claim Query Code],
    'N',
    DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
 from [ACO].[dbo].['PA_Header_Temp'] PAHT
    inner join #tmp_hic_cancels THC on PAHT.[HIC #] = THC.[HIC #] and
                                    PAHT.[Claim Type Code] = THC.[Claim Type Code] and 
                                    PAHT.[Provider Oscar #] = THC.[Provider Oscar #] and
                                    PAHT.[Claim From Date] = THC.[Claim From Date] and
                                     PAHT.[Claim Thru Date] = THC.[Claim Thru Date]
where PAHT.[Claim Type Code] <> 10
    and EXISTS (select 
                [Claim Adjustment Type Code] 
            from [ACO].[dbo].['PA_Header_Temp']
            where 
                [HIC #] = PAHT.[HIC #]
                and [Provider Oscar #] = PAHT.[Provider Oscar #]
                and [Claim Type Code] = PAHT.[Claim Type Code]
                and [Claim From Date] = PAHT.[Claim From Date]
                and [Claim Adjustment Type Code] = PAHT.[Claim Adjustment Type Code]
                and [Claim Adjustment Type Code]  = 2)

insert into  #tmp_hic_final  
select distinct PAHT.[ID],
    PAHT.[HIC #], 
    PAHT.[Provider Oscar #], 
    PAHT.[Claim Type Code],
    PAHT.[Claim From Date], 
    PAHT.[Claim Thru Date],
    PAHT.[Claim Adjustment Type Code],
    PAHT.[Claim Effective Date],
    PAHT.[Current ClaimID],
    PAHT.[Claim Bill Facility Type Code],
    PAHT.[Claim Bill Classification Code],
    PAHT.[Principal Diagnosis Code],
    PAHT.[Admitting Diagnosis Code],
    PAHT.[Claim Medicare Non Payment Reason Code],
    PAHT.[Claim Payment Amount],
    PAHT.[Claim NCH Primary Payer Code],
    PAHT.[FIPS state Code],
    PAHT.[Bene Patient Status Code],
    PAHT.[Diagnosis Related Group Code],
    PAHT.[Claim Outpatient Service Type Code],
    PAHT.[Facility Provider NPI #],
    PAHT.[Operating Provider NPI #],
    PAHT.[Attending provider NPI #],
    PAHT.[Other Provider NPI #],
    PAHT.[Claim IDR Load Date],
    PAHT.[Bene Equitable BIC HICN #],
    PAHT.[Claim Admission Type Code],
    PAHT.[Claim Admission Source Code],
    PAHT.[Claim Bill Frequency Code],
    PAHT.[Claim Query Code],
    'N',
    DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
from [ACO].[dbo].['PA_Header_Temp'] PAHT
    inner join #tmp_hic_cancels THC on PAHT.[HIC #] = THC.[HIC #] and
                                    PAHT.[Claim Type Code] = THC.[Claim Type Code] and 
                                    PAHT.[Provider Oscar #] = THC.[Provider Oscar #] and
                                    PAHT.[Claim From Date] = THC.[Claim From Date] and
                                     PAHT.[Claim Thru Date] = THC.[Claim Thru Date]
where PAHT.[Claim Type Code] <> 10
    and EXISTS (select 
                [Claim Adjustment Type Code] 
            from [ACO].[dbo].['PA_Header_Temp']
            where 
                [HIC #] = PAHT.[HIC #]
                and [Provider Oscar #] = PAHT.[Provider Oscar #]
                and [Claim Type Code] = PAHT.[Claim Type Code]
                and [Claim From Date] = PAHT.[Claim From Date]
                and [Claim Adjustment Type Code] = PAHT.[Claim Adjustment Type Code]
                and [Claim Adjustment Type Code]  <> 2)