返回所有非 NULL 值都相等的行

Cad*_*oux 7 sql-server pivot t-sql

是否有一个更简单的 T-SQL 构造“所有这些列在一行上都相等(忽略 NULL)” - 我想说有效:

WHERE MIN(a, b, c) = MAX(a, b, c) OR COALESCE(a, b, c) IS NULL
Run Code Online (Sandbox Code Playgroud)
  • 这将相当于所有排列的 COALESCE 相等 - 但没有非聚合 MIN/MAX 函数

3 列的替代方法是:

WHERE ( 
COALESCE(a, b, c) = COALESCE(b, c, a) 
AND COALESCE(a, b, c) = COALESCE(c, a, b) 
AND COALESCE(a, b, c) = COALESCE(b, a, c) 
AND COALESCE(a, b, c) = COALESCE(a, c, b) 
AND COALESCE(a, b, c) = COALESCE(c, b, a) 
) 
OR COALESCE(a, b, c) IS NULL
Run Code Online (Sandbox Code Playgroud)

即“所有非空列 a、b、c 必须相等,否则所有列都可能为空”

显然,可以完成 PIVOT/UNPIVOT 实现或复杂的 CASE 语句,但我正在寻找相对简单的东西。

在这种情况下,列都是整数,所以我想可能有一个我可以弄清楚的数学技巧。

Pau*_*ite 8

我能找到的最紧凑的语法是:

SELECT * 
FROM @T AS t
WHERE EXISTS 
(
    SELECT ISNULL(ISNULL(a, b), c) 
    INTERSECT 
    SELECT ISNULL(ISNULL(b, c), a) 
    INTERSECT 
    SELECT ISNULL(ISNULL(c, a), b)
);
Run Code Online (Sandbox Code Playgroud)

基于我的一篇旧博客文章中的一个想法,该文章描述了如何使用INTERSECTEXCEPT替换a <> b OR (a IS NULL AND b IS NULL)NOT EXISTS (a INTERSECT b) 之类的比较。


Mik*_*son 5

您可以使用 对列进行聚合,VALUES(a),(b),(c)或者如果您使用的是 2008 之前的 SQL Server,则可以这样做SELECT a UNION ALL SELECT b UNION ALL SELECT c

SELECT *
FROM @T
WHERE (SELECT MIN(x) FROM (VALUES(a),(b),(c)) AS T(x)) =
      (SELECT MAX(x) FROM (VALUES(a),(b),(c)) AS T(x)) OR
      COALESCE(a, b, c) IS NULL;
Run Code Online (Sandbox Code Playgroud)

更新:

看起来应该快一点的东西。

SELECT T.*
FROM @T AS T
CROSS APPLY (
            SELECT MIN(x), MAX(x)
            FROM (VALUES(T.a),(T.b),(T.c)) AS X(x)
            ) AS X(MinValue, MaxValue)
WHERE X.MinValue = X.MaxValue OR
      (X.MinValue IS NULL AND X.MaxValue IS NULL);
Run Code Online (Sandbox Code Playgroud)


ype*_*eᵀᴹ 5

@Mikael 答案的变体:

SELECT * 
FROM @T
WHERE (SELECT COUNT(DISTINCT x) FROM (VALUES(a),(b),(c)) AS T(x))
      <= 1 ; 
Run Code Online (Sandbox Code Playgroud)