英文:
How to Add an Exception to a SQL 'Quality Check' Rule?
问题
我有以下查询:
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',那是可以的。
所有其他基金都有基金和经理姓名之间的一对一关系。
如何将这个例外情况添加到我的查询中?
英文:
I have the following query:
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
The results of this query show when a Manager is incorrectly assigned to a fund.
The REFERENCE_TABLE
is the source of truth and shows the correct FUND
and MGR_NM
assignments. However, I need to add one exception to this rule: when FUND = 'BOSTON'
, it's okay if MANAGER_NAME
= 'Kim, John, or Danny'.
All other funds have a 1:1 relationship between fund and manager name.
How can I add this exception to my query?
答案1
得分: 3
> 显示所有结果,其中MANAGER_NAME
与MGR_NM
不匹配,除非FUND
是'BOSTON',那么如果MANAGER_NAME
是'Kim, John, or Danny'之一,也是可以的。
这似乎需要在您的条件中使用一个简单的OR
表达式,但我们需要反转对'Kim, John, or Danny'的匹配,并在基金是'BOSTON'且MANAGER_NAME
不是'Kim, John, or Danny'之一时返回。
但这并不是太简单,当将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
,这些是我们想要查看的行。
英文:
> Show all results where MANAGER_NAME
does not match MGR_NM
, unless the FUND
is 'BOSTON', then it is okay if MANAGER_NAME
is one of 'Kim, John, or Danny'
Sounds like a case for a simple OR
expression in your criteria, but we need to invert the match on 'Kim, John, or Danny' and return if the fund is 'BOSTON' and the MANAGER_NAME
is NOT one of 'Kim, John, or Danny'
But it's not too simple, be careful when injecting OR
operator into your criteria though, if you are not using brackets to separate the logical expressions in the criteria then OR
will compare either side of the operator independently which can produce undesirable results.
In the following solution no brackets are used, but we have to evaluate a non-match for the BOSTON
fund in the original logic so that 'Kim', 'John', 'Danny' are not considered valid for other funds:
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')
You might prefer to use brackets to make the expression more readable, or to highlight the exceptional case. The RDBMS is likely to expand the brackets on evaluation anyway so it shouldn't have an impact on performance either way, but it does allow us to use syntax like this if it is helpful:
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')
)
While this should work, the question is why are 'Kim', 'John', 'Danny' valid? If REFERENCE_TABLE
is the source of truth then you could allow multiple entries for each fund in this table, then you wouldn't need to hardcode the specific case for 'BOSTON' at all and we can use an OUTER JOIN
to return only the non-correlated rows:
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
This works because all the valid manager will match and will have a non-null value for C.FUND
. However all rows that do not find a corresponding match in the REFERENCE_TABLE
will have a value of null
for C.FUND
, these are the rows that we want to see.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论