SQL 中多列“级联”约束的优雅语法?
Posted
技术标签:
【中文标题】SQL 中多列“级联”约束的优雅语法?【英文标题】:Elegant syntax for multi-column "cascading" constraint in SQL? 【发布时间】:2009-02-03 17:34:45 【问题描述】:我正在构建一个查询,该查询自然会返回一个结果,该结果具有多个列的值,以及一些整数值分组列(指示特定值列是否被小计,但这本身与我的问题无关)。我想对这个查询的分组列施加一个约束,如果所有分组列 1 - (n-1) 只接受分组列 n 非零的行也是非零的。
似乎应该有一个很好的方式来用 SQL 来表达这一点,但到目前为止我能想到的只是相当麻烦
where ((grp1 = 0 AND grp2 = 0 AND grp3 = 0 AND ... AND grpn = 0)
or (grp1 = 1 AND grp2 = 0 AND grp3 = 0 AND ... AND grpn = 0)
or (grp1 = 1 AND grp2 = 1 AND grp3 = 0 AND ... AND grpn = 0)
...
or (grp1 = 1 AND grp2 = 1 AND grp3 = 1 AND ... AND grpn = 1)
如果您正在阅读它,则更难理解这个概念,看起来 SQL 引擎更难进行体面的优化,并且通常也会阻塞日志,掩埋重要的部分噪音中的 SQL。
由于这个概念似乎并不太不寻常,我希望有一种更好的方式来表达它,这种方式通常会更简洁,并希望在服务器本身上性能更高(假设我的幼稚版本不会高效)。
【问题讨论】:
根据您提供的信息,Ben 的解决方案似乎是正确的,但是如果您提供问题的完整描述(架构、完整 SQL 等),那么有人可能会为您提供更好的从不同的方向看问题的解决方案。 是 (n) 一个变量,还是架构中的一个固定(但很大)值? 【参考方案1】:你说值是整数。他们可以是消极的吗?如果没有,您可以使用一组比较:
where (grp1 >= grp2 and grp2 >= grp3 ...)
编辑:实际上,我在这里也假设非零值必须为 1...但如果不是这种情况,该原则仍然可以应用,我想。
【讨论】:
这正是我正在寻找的东西,谢谢。事实证明,是的,列的值始终是 1 和 0(我真的应该澄清这一点),这样就可以正常工作了。 顺便说一句,您说得对,该原则仍然适用于非零值可以是任何值的一般情况。这可以通过“where ((grp2 = 0 or grp 1 0) and (grp3 = 0 or grp2 0) and ...”来涵盖,所以很高兴知道如果情况略有变化它仍然可以工作。 【参考方案2】:如果 (n) 是固定的,那么 Ben 的答案似乎是最好的。
如果您的数据已标准化并且 (n) 是可变的,我会假设您有类似这样的数据...
data_fk | grp_id | flag
然后您要搜索 data_fk,其中各种 grp_id 的标志符合您设定的规则。该规则(在我看来)可以重述为...
(flag = 1 的最高 group_id)应该是(flag = 0 的最低 group_id)之前的 grp_id,或者所有标志都为 1,或者所有标志都为 0。
SELECT
data_fk
FROM
a_table
GROUP BY
data_fk
HAVING
ISNULL(MIN(CASE WHEN flag = 0 THEN grp_id ELSE NULL END), MAX(grp_id) + 1)
=
MAX(CASE WHEN flag = 1 THEN grp_id ELSE 0 END) + 1
【讨论】:
以上是关于SQL 中多列“级联”约束的优雅语法?的主要内容,如果未能解决你的问题,请参考以下文章