Oracle中的此查询有什么问题

时间:2015-08-10 15:46:10

标签: sql oracle oracle11g

我有以下查询。但它并没有带来我想要的结果。

如果UPPER(PCK.Keyid)='TLMAPICONFIGMGR.USEDB'和UPPER(PCK.DEFAULTKEYIDVALUE)='FALSE'那么,它应该只带来这条记录。如果PCK.DEFAULTKEYIDVALUE不是False,它应该带回所有其他记录。

虽然在数据库中它是错误的,但它会带来包括这一个在内的所有记录。

如何解决这个问题?

SELECT
    COALESCE(Cast(PCBS.keyId as VarChar2(255)), cast(PC.Keyid as varchar2(255)), cast(PCK.KeyId as varchar2(255))) as Key,
    COALESCE(Cast(PCBS.KeyIdValue as VarChar2(255)), cast(PC.KeyIdValue as varchar2(255)), cast(PCK.DefaultKeyIdValue as varchar2(255))) as value
FROM
    PodServer_Tab PS
    JOIN PodConfigKey_tab PCK
        ON PCK.KeyId = PCK.KEYID 
    LEFT OUTER JOIN PodConfig_Tab PC 
        ON PS.PodId = PC.PodId
    LEFT JOIN PodConfigByServer_Tab PCBS 
        ON PS.PODID = PCBS.PODID 
        AND PS.ServerName = PCBS.ServerName
        AND PCBS.KeyId = PC.KeyId 
WHERE PS.PodId =  p_podId 
    AND PS.Servername = p_serverName
    AND (
        (UPPER(PCK.Keyid) = 'TLMAPICONFIGMGR.USEDB' AND UPPER(PCK.DEFAULTKEYIDVALUE) = 'FALSE') 
        OR
        (UPPER(PCK.Keyid) != 'TLMAPICONFIGMGR.USEDB')
        ); 

2 个答案:

答案 0 :(得分:2)

过滤器适用于每一行。

AND (
    (UPPER(PCK.Keyid) = 'TLMAPICONFIGMGR.USEDB' AND UPPER(PCK.DEFAULTKEYIDVALUE) = 'FALSE') 
    OR
    (UPPER(PCK.Keyid) != 'TLMAPICONFIGMGR.USEDB')
    ); 

对于每个行,UPPER(PCK.Keyid)'TLMAPICONFIGMGR.USEDB'匹配或不匹配。将永远返回不匹配的每一行,因为没有任何声明它不应该是。

唯一排除任何内容的是UPPER(PCK.DEFAULTKEYIDVALUE) 等于'FALSE',在这种情况下该行将被排除。它对与Keyid不匹配的行没有影响,仅对那些行有效。

无论默认设置为何,所有其他Keyid值始终匹配。

如果您只想查看单行或除该行之外的所有内容,则您需要一次看起来比一行宽。您可以添加exists子句,例如:

AND (
    (UPPER(PCK.Keyid) = 'TLMAPICONFIGMGR.USEDB' AND UPPER(PCK.DEFAULTKEYIDVALUE) = 'FALSE') 
    OR
    (UPPER(PCK.Keyid) != 'TLMAPICONFIGMGR.USEDB'
      AND NOT EXISTS (
        SELECT 1 FROM PodConfigKey_tab PCK2
        WHERE PCK2.KeyId = PCK.KEYID
        AND UPPER(PCK2.Keyid) = 'TLMAPICONFIGMGR.USEDB'
        AND UPPER(PCK2.DEFAULTKEYIDVALUE) = 'FALSE'
      )
    )
    ); 

您可以使用具有分析函数的子查询,但是您查找单个值可能没有太大的好处,相关的自联接也不会太昂贵。

我认为这与您所描述的问题无关,但目前您的连接条件似乎也已断开:

JOIN PodConfigKey_tab PCK
    ON PCK.KeyId = PCK.KEYID 

应该是:

JOIN PodConfigKey_tab PCK
    ON PS.KeyId = PCK.KEYID 

否则它是交叉连接而不是内连接;在这种情况下,使用起来会更清楚:

CROSS JOIN PodConfigKey_tab PCK

(没有ON子句,因为交叉连接不允许一个)明确表示意图。

答案 1 :(得分:1)

 OR
        (UPPER(PCK.Keyid) != 'TLMAPICONFIGMGR.USEDB')

以上就是说给我看看keyid!='TLMAPICONFIGMGR.USEDB'的一切,所以你会得到一切(假设服务器名匹配)