我有以下问题:
SELECT A.ID, A.FUND, B.MANAGER_NAME, C.FUND, C.MGR_NM
FROM TABLE_1 A
LEFT JOIN TABLE_2 B ON
A.ID = B.ID
LEFT JOIN REFERENCE_TABLE C ON
A.FUND = C.FUND
WHERE
B.MANAGER_NAME != C.MGR_NM
此查询的结果显示经理何时被错误地分配给基金。
REFERENCE_TABLE
是真理的来源,并显示正确的 FUND
和 MGR_NM
作业。但是,我需要为这条规则添加一个例外:当FUND = 'BOSTON'
时,如果MANAGER_NAME
= 'Kim, John, or Danny' 就可以了。
所有其他基金在基金和经理姓名之间具有 1:1 的关系。
如何将此异常添加到我的查询中?
Show all results where
does not matchMANAGER_NAME
, unless theMGR_NM
is 'BOSTON', then it is okay ifFUND
is one of the 'Kim, John, or Danny'MANAGER_NAME
听起来像是在您的标准中使用简单的
OR
表达式的情况,但我们需要反转“Kim、John 或 Danny”的匹配项,如果基金是“BOSTON”并且MANAGER_NAME
不是其中之一,则返回“金、约翰或丹尼”
但这并不太简单,但是在将
OR
运算符注入您的条件时要小心,如果您没有使用括号来分隔条件中的逻辑表达式,那么 OR
将独立比较运算符的任一侧,这可能会产生不良结果结果。
在下面的解决方案中没有使用括号,但我们必须在原始逻辑中评估
BOSTON
基金的不匹配,以便'Kim','John','Danny'被认为对其他基金无效:
SELECT A.ID, A.FUND, B.MANAGER_NAME, C.FUND, C.MGR_NM
FROM TABLE_1 A
LEFT JOIN TABLE_2 B ON A.ID = B.ID
LEFT JOIN REFERENCE_TABLE C ON A.FUND = C.FUND
WHERE
A.FUND <> 'BOSTON'
AND B.MANAGER_NAME != C.MGR_NM
OR A.FUND = 'BOSTON'
AND B.MANAGER_NAME != C.MGR_NM
AND B.MANAGER_NAME NOT IN ('Kim', 'John', 'Danny')
您可能更喜欢使用方括号使表达式更具可读性,或突出显示特殊情况。无论如何,RDBMS 可能会扩展评估的括号,因此它不会对性能产生任何影响,但它确实允许我们使用这样的语法,如果它有帮助的话:
SELECT A.ID, A.FUND, B.MANAGER_NAME, C.FUND, C.MGR_NM
FROM TABLE_1 A
LEFT JOIN TABLE_2 B ON A.ID = B.ID
LEFT JOIN REFERENCE_TABLE C ON A.FUND = C.FUND
WHERE
B.MANAGER_NAME != C.MGR_NM
AND (
A.FUND <> 'BOSTON'
OR A.FUND = 'BOSTON'
AND B.MANAGER_NAME NOT IN ('Kim', 'John', 'Danny')
)
虽然这应该可行,但问题是为什么“Kim”、“John”、“Danny”有效?如果
REFERENCE_TABLE
是真实来源,那么您可以允许此表中每个基金的多个条目,那么您根本不需要硬编码 'BOSTON' 的具体情况,我们可以使用 OUTER JOIN
只返回不相关的行:
SELECT A.ID, A.FUND, B.MANAGER_NAME, C.FUND, C.MGR_NM
FROM TABLE_1 A
LEFT JOIN TABLE_2 B ON A.ID = B.ID
LEFT OUTER JOIN REFERENCE_TABLE C ON A.FUND = C.FUND
AND B.MANAGER_NAME = C.MGR_NM
WHERE
C.FUND IS NULL
这是可行的,因为所有有效的管理器都将匹配,并且
C.FUND
将具有非空值。然而,所有在REFERENCE_TABLE
中找不到相应匹配项的行对于null
的值为C.FUND
,这些是我们想要看到的行。