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 中多列“级联”约束的优雅语法?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server-一次删除具有IF EXISTS的多列

SQL外键约束&&多表查询&&级联删除&&子查询

SQL外键约束&&多表查询&&级联删除&&子查询

SQL外键约束&&多表查询&&级联删除&&子查询

SQL删除多列语句

SQL Server2012创建约束图解