比较一行中的每一列,如果其中任何一列不同则返回错误

Joh*_*yen 5 sql-server sql-server-2008-r2 excel

我正在尝试查找在同一行中具有不同值的任何标识符。

+------------+--------+--------+--------+--------+
| Identifier | Value1 | Value2 | Value3 | Value4 |
| f001       | a1     | a2     | a2     | a2     |
| f002       | a4     | a4     | a4     | a5     |
| f003       | a2     | a2     | a2     |        |
| f004       | a1     | a1     | a1     | a1     |
| f002       | a9     |        |        |        |
+------------+--------+--------+--------+--------+
Run Code Online (Sandbox Code Playgroud)

例如,


第一个标识符返回“MisMatch”,
第二个标识符返回“MisMatch”,
第三个标识符返回“NoIssue”,
第四个标识符返回“Mismatch”,
第五个标识符返回“NoIssue”,

任何帮助都会很棒,我被困在这一点上。

有些行有数百列,而其他行只有一列。我希望能够找到包含任何不匹配的任何行。

我正在使用 SQL Server 2008 R2。

Mar*_*ith 7

我看到这个问题被标记为 Excel 和 SQL Server。

在此处输入图片说明

在 Excel 中,您可以使用此处的方法

上面单元格F2中的公式是

=IF(SUM(IF(FREQUENCY(IF(LEN(B2:E2)>0,MATCH(B2:E2,B2:E2,0),""), IF(LEN(B2:E2)>0,MATCH(B2:E2,B2:E2,0),""))>0,1))>1,"MisMatch","Match")
Run Code Online (Sandbox Code Playgroud)

注意链接文章中的注释

本例中的公式必须作为数组公式输入。选择每个包含公式的单元格,按F2,然后按 CTRL+ SHIFT+ ENTER

然后花括号将出现在公式栏中的公式周围

在此处输入图片说明

另一种(SQL Server)方式(归功于Geoff Patterson的改进)是

SELECT T.Identifier,
       CASE
         WHEN min_val <> max_val
           THEN 'MisMatch'
         ELSE 'NoIssue'
       END
FROM   @T T
       CROSS APPLY (SELECT MIN(Val),
                      MAX(Val)
                    FROM   (VALUES (Value1),
                                   (Value2),
                                   (Value3),
                                   (Value4)) V(Val)) V(min_val, max_val) 
Run Code Online (Sandbox Code Playgroud)

它应该适用于提到的“数百列”。

尽管与简单的计算标量相比,它在计划中引入了一些额外的复杂性。

在此处输入图片说明


Jon*_*ite 2

我会做这样的事情。您可能需要根据您想要如何处理 NULL 与空字符串来编辑语法,并且假定 VALUE 对于所有字段都是相同的数据类型。

IF OBJECT_ID('tempdb..#Test1') IS NOT NULL
BEGIN
    DROP TABLE #Test1
END

CREATE TABLE #Test1
    (
    TestID VARCHAR(10) NOT NULL PRIMARY KEY
    , Value1 VARCHAR(10) NULL
    , Value2 VARCHAR(10) NULL
    , Value3 VARCHAR(10) NULL
    , Value4 VARCHAR(10) NULL
    )

INSERT INTO #Test1
(TestID, Value1, Value2, Value3, Value4)
VALUES 
('f001', 'a1', 'a2', 'a2', 'a2')
, ('f002', 'a4', 'a4', 'a4', 'a5')
, ('f003', 'a2', 'a2', 'a2', NULL)
, ('f004', 'a1', 'a1', 'a1', 'a1')
, ('f005', 'a9', NULL, NULL, NULL)

SELECT TestID, Value1, Value2, Value3, Value4 FROM #Test1


;WITH CTE_Test AS
(
    SELECT TestID
        , Value1 AS Value
    FROM #Test1
    UNION ALL
    SELECT TestID
        , Value2 AS Value
    FROM #Test1
    UNION ALL
    SELECT TestID
        , Value3 AS Value
    FROM #Test1
    UNION ALL
    SELECT TestID
        , Value4 AS Value
    FROM #Test1
)
, CTE_TestDistinct AS
(
    SELECT DISTINCT TestID, Value 
    FROM CTE_Test 
    WHERE Value IS NOT NULL
)
SELECT CTE_TestDistinct.TestID
    , Issue = CASE WHEN COUNT(Value) = 1 THEN 'NoIssue'
                    ELSE 'MisMatch'
                    END
FROM CTE_TestDistinct
GROUP BY TestID
UNION ALL
SELECT TestID 
    , 'NoIssue'
FROM #Test1
WHERE NOT(TestID IN (SELECT C.TestID FROM CTE_TestDistinct C))


IF OBJECT_ID('tempdb..#Test1') IS NOT NULL
BEGIN
    DROP TABLE #Test1
END
Run Code Online (Sandbox Code Playgroud)

我想到了另一种方法。同样,这对数据做出了几个假设,但使用相同的源数据返回相同的答案,同时实际上是单行。

SELECT TestID
    , CASE WHEN AllHashed <> Value1RHashed THEN 'Mismatch' ELSE 'NoIssue' END
FROM (
SELECT TestID
    , AllHashed = HASHBYTES('md5',(ISNULL(Value1, COALESCE(Value1, Value2, Value3, Value4, '')) 
                                    + ISNULL(Value2, COALESCE(Value1, Value2, Value3, Value4, '')) 
                                    + ISNULL(Value3, COALESCE(Value1, Value2, Value3, Value4, '')) 
                                    + ISNULL(Value4,COALESCE(Value1, Value2, Value3, Value4, ''))))
    , Value1RHashed = HASHBYTES('md5', REPLICATE(COALESCE(Value1, Value2, Value3, Value4, ''), 4))
FROM #Test1
) D
Run Code Online (Sandbox Code Playgroud)