简体   繁体   English

PL SQL / Oracle中的CTE WITH子句有什么问题?

[英]What is the issue with this CTE WITH clause in PL SQL /Oracle?

I have below query. 我有以下查询。 The below query WITH CTE, it is returning 4 Records. 下面的查询WITH CTE,它返回4条记录。

As I gave the comments, the below Select query has 55 Records and with And clause it should remove those 4 Records and return 51 records. 正如我给出的评论,下面的Select查询具有55条记录,使用And子句应删除这4条记录并返回51条记录。 Instead it is returning simply those 4 records only. 而是仅返回这4条记录。

Just for testing I commented that AND clause and then it is functioning as expected and returning 55+4 = total of 59 Records. 仅出于测试目的,我评论了AND子句,然后它按预期运行,并返回55 + 4 =总共59条记录。

How to fix this WITH CTE. 如何使用CTE解决此问题。 What is wrong? 怎么了?

CREATE OR REPLACE PROCEDURE CUSTCONNECT.sp_GetPodConfigurationGridData( 
p_podURL            IN varchar2,  --PodUrl
p_serverType        IN varchar2,
p_serverName        IN varchar2,
p_publishedDate     IN date,
P_RECORDSET         OUT SYS_REFCURSOR 
)
AS
BEGIN
OPEN P_RECORDSET FOR

--This has total of 4 Records
WITH PodServerRecords(Key, value, Overwrite, ServerName, ServerType, PublishDate ) AS (    
 select
         PC.KeyId as Key, KeyIdValue as value, 'Pod' as Overwrite, ''  as ServerName,  '' as Servertype, PC.PublishDate 
    from (select 
            Keylog.*, row_number() over (partition by Keylog.KeyId order by Keylog.PublishDate desc) as RowNu
          from PodConfigLog_Tab Keylog
          where Keylog.URL = p_podURL 
          and Keylog.PublishDate >= p_publishedDate and Keylog.PublishDate <= sysdate 
          ) PC 
    where PC.RowNu = 1 and PC.IsActive = 'T'
    UNION
    select 
        PCBS.KeyId as Key, KeyIdValue as value, 'Server' as Overwrite,  PCBS.ServerName, Servertype, PCBS.PublishDate
    from (select 
            Serlog.*, PS.ServerType, row_number() over (partition by Serlog.KeyId order by Serlog.PublishDate desc) as RowNu
          from PodConfigByServerLog_Tab Serlog 
          join PodServer_tab PS on PS.ServerName = Serlog.ServerName 
          and Serlog.URL = PS.URL
          where Serlog.URL = p_podURL 
          and Serlog.ServerName = p_serverName 
          and Serlog.PublishDate >= p_publishedDate and Serlog.PublishDate <= sysdate 
          ) PCBS 
    where PCBS.RowNu = 1 and PCBS.IsActive = 'T'

)

    --This has total of 55 Records 
    select
        PCK.KeyId as Key ,DefaultKeyIdValue as value,'Default' as Overwrite, '' as ServerName,  '' as Servertype, PCK.PublishDate
    from 
        (select 
            Keylog.*, row_number() over (partition by Keylog.KeyId order by Keylog.PublishDate desc) as RowNu
          from PodConfigKeyLog_Tab Keylog
          where Keylog.PublishDate >= p_publishedDate and Keylog.PublishDate <= sysdate 
          ) PCK
    join POD_TAB PS on PS.URL = p_podURL
    where PCK.RowNu = 1 and PCK.IsActive = 'T'
    --This And caluse should remove those 4 Records and total Records should be 51. 
    and PCK.KeyId not in (
        select KeyId
        from PodServerRecords 
    )
    UNION
    --This is total of 4 Records
    SELECT 
        Key, value, Overwrite, ServerName, ServerType, PublishDate
    FROM PodServerRecords 
    Order By Key;

END;
/

Your problem is that the CTE does not have a column called KeyId . 您的问题是CTE没有名为KeyId的列。 You renamed it to Key . 您已将其重命名为Key However, NOT IN has unexpected behavior when there are NULL values. 但是,当存在NULL值时, NOT IN具有意外行为。 You can fix this by eliminating them directly: 您可以通过直接消除它们来解决此问题:

PCK.KeyId not in (
        select psr.KeyId
        from PodServerRecords psr
        where psr.KeyId IS NOT NULL 
    )

I recommend using NOT EXISTS instead: 我建议改用NOT EXISTS

NOT EXISTS (select 1
            from PodServerRecords psr
            where psr.KeyId = PCK.KeyId
           )

This may fix your problem. 这可能会解决您的问题。

Actually, I don't see a KeyId in your CTE. 实际上,我在您的CTE KeyId不到KeyId So, I think you want: 所以,我想你想要:

NOT EXISTS (select 1
            from PodServerRecords psr
            where psr.Key = PCK.KeyId
           )

Note the preceding statements will return errors, indicating that the problem is the misnamed column. 请注意,前面的语句将返回错误,表明问题是列名不正确。

I think you should remove that UNION part of your query cause it's readding those 4 records from PodServerRecords . 我认为您应该删除查询的UNION部分,因为它正在从PodServerRecords读取这4条记录。 Your query should rather be 您的查询应该是

 --This has total of 55 Records 

    select
        PCK.KeyId as Key ,DefaultKeyIdValue as value,'Default' as Overwrite, '' as ServerName,  '' as Servertype, PCK.PublishDate
    from 
        (select 
            Keylog.*, row_number() over (partition by Keylog.KeyId order by Keylog.PublishDate desc) as RowNu
          from PodConfigKeyLog_Tab Keylog
          where Keylog.PublishDate >= p_publishedDate and Keylog.PublishDate <= sysdate 
          ) PCK
    join POD_TAB PS on PS.URL = p_podURL
    where PCK.RowNu = 1 and PCK.IsActive = 'T'
    --This And caluse should remove those 4 Records and total Records should be 51. 
    and PCK.KeyId not in (
        select KeyId
        from PodServerRecords 
    );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM