Sql-Server

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

  • November 17, 2019

是否有一個更簡單的 T-SQL 構造來表示“所有這些列在一行上都相等(忽略 NULL)” - 我想說的是有效:

WHERE MIN(a, b, c) = MAX(a, b, c) OR COALESCE(a, b, c) IS NULL
  • 這將相當於所有排列的 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

即“所有非 NULL 列 a、b、c 必須相等,否則所有列可能為空”

顯然,可以完成 PIVOT/UNPIVOT 實現或複雜的 CASE 語句,但我正在尋找相對簡單的東西。

在這種情況下,列都是整數,所以我想可能有一個數學技巧我可以弄清楚。

我能找到的最緊湊的語法是:

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)
);

基於我的一篇舊部落格文章中的一個想法,該文章描述瞭如何使用INTERSECT和替換EXCEPT比較(如)。a <> b OR (a IS NULL AND b IS NULL)``NOT EXISTS (a INTERSECT b

VALUES(a),(b),(c)您可以使用或者如果您使用 SQL Server pre 2008 可以對列進行聚合,您可以這樣做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;

更新:

看起來應該快一點的東西。

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);

引用自:https://dba.stackexchange.com/questions/33708