【问题标题】:What is the issue with this CTE WITH clause in PL SQL /Oracle?PL SQL /Oracle 中的这个 CTE WITH 子句有什么问题?
【发布时间】:2015-09-03 13:49:19
【问题描述】:

我有以下查询。 下面的查询 WITH CTE,它返回 4 条记录。

正如我给出的 cmets,下面的 Select 查询有 55 条记录,并且使用 And 子句应该删除这 4 条记录并返回 51 条记录。相反,它只返回这 4 条记录。

只是为了测试,我评论了那个 AND 子句,然后它按预期运行并返回 55+4 = 总共 59 条记录。

如何通过 CTE 解决此问题。怎么了?

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;
/

【问题讨论】:

  • 很难找到您提供的不同查询之间的相似之处。为什么他们应该返回相同的数字?
  • 我认为您应该删除查询中的 UNION 部分,因为它正在从 PodServerRecords 读取这 4 条记录

标签: sql oracle plsql common-table-expression


【解决方案1】:

您的问题是 CTE 没有名为 KeyId 的列。您将其重命名为 Key。但是,当存在 NULL 值时,NOT IN 会出现意外行为。您可以通过直接消除它们来解决此问题:

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

我建议改用NOT EXISTS

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

这可能会解决您的问题。

实际上,我在您的 CTE 中没有看到 KeyId。所以,我想你想要:

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

注意前面的语句会返回错误,说明问题是列名错误。

【讨论】:

    【解决方案2】:

    我认为您应该删除查询中的 UNION 部分,因为它正在从 PodServerRecords 读取这 4 条记录。您的查询应该是

     --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 
        );
    

    【讨论】:

      猜你喜欢
      • 2011-08-28
      • 2011-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      相关资源
      最近更新 更多