【问题标题】:How do I compare two columns for equality in SQL Server?如何在 SQL Server 中比较两列是否相等?
【发布时间】:2010-12-10 14:34:07
【问题描述】:

我有两列根据特定条件连接在一起,但我还想检查其他两列是否相同,如果它们相同则返回一个位字段。

有没有比使用 CASE WHEN 更简单的解决方案?

理想情况下我可以使用:

    SELECT Column1 = Column2 AS MyDesiredResult
      FROM Table1
INNER JOIN Table2 ON Table1.PrimaryKey = Table2.ForeignKey

【问题讨论】:

  • 在输出中返回一个位字段/列?
  • 非常好的问题,希望语法有效。注意:在 C++ 和其他 C 语言中,它们使用 '=' 进行赋值操作,使用 == 进行比较。

标签: sql sql-server tsql


【解决方案1】:

CASE 有什么问题?为了看到结果,您至少需要一个字节,这就是您使用单个字符得到的结果。

CASE WHEN COLUMN1 = COLUMN2 THEN '1' ELSE '0' END AS MyDesiredResult

应该可以正常工作,并且对于所有意图和目的而言,完成与使用位字段相同的事情。

【讨论】:

  • 我正在寻找一些简短的东西。 CASE WHEN 似乎对我来说太长了。
  • 我发布了实际的 CASE WHEN 声明 - 您需要多短?几个字符的 SQL 语句长度差异是没有意义的,并且在您不需要的地方保持简洁会使您的代码以后更难维护。避免使用正确的构造来尝试找到比键入要短几个字母的构造通常是个坏主意。
  • 考虑使用数字而不是字符:“CASE WHEN COLUMN1 = COLUMN2 THEN 1 ELSE 0 END AS MyDesiredResult”,但我同意 Ken,这是最好的选择。
  • @Rob:我认为 Orion 会知道在实际使用中是 1 还是 '1' 更有用。 :-)
  • 当您只想定义 0 或 1 的情况时,我通常会显式使用 BIT。只是喜欢:...然后转换(1位)...
【解决方案2】:

CASE WHEN 是更好的选择

SELECT 
  CASE WHEN COLUMN1 = COLUMN2 
    THEN '1' 
    ELSE '0' 
  END 
  AS MyDesiredResult
FROM Table1
INNER JOIN Table2 ON Table1.PrimaryKey = Table2.ForeignKey

【讨论】:

    【解决方案3】:

    使用IIF?这取决于 SQL Server 的版本。

    SELECT
    IIF(Column1 = Column2, 1, 0) AS MyDesiredResult
    FROM Table;
    

    【讨论】:

      【解决方案4】:

      我也会选择CASE WHEN

      根据您实际想要做的事情,可能还有其他选择,例如使用外连接或其他什么,但在这种情况下,这似乎不是您所需要的。

      【讨论】:

        【解决方案5】:

        关于 David Elizondo 的回答,这可能会产生误报。它也不会在值不匹配的地方给出零。

        代码

        DECLARE @t1 TABLE (
            ColID   int     IDENTITY,
            Col2    int
        )
        
        DECLARE @t2 TABLE (
            ColID   int     IDENTITY,
            Col2    int
        )
        
        INSERT INTO @t1 (Col2) VALUES (123)
        INSERT INTO @t1 (Col2) VALUES (234)
        INSERT INTO @t1 (Col2) VALUES (456)
        INSERT INTO @t1 (Col2) VALUES (1)
        
        INSERT INTO @t2 (Col2) VALUES (123)
        INSERT INTO @t2 (Col2) VALUES (345)
        INSERT INTO @t2 (Col2) VALUES (456)
        INSERT INTO @t2 (Col2) VALUES (2)
        
        SELECT
            t1.Col2 AS t1Col2,
            t2.Col2 AS t2Col2,
            ISNULL(NULLIF(t1.Col2, t2.Col2), 1) AS MyDesiredResult
        FROM @t1 AS t1
        JOIN @t2 AS t2 ON t1.ColID = t2.ColID
        

        结果

             t1Col2      t2Col2 MyDesiredResult
        ----------- ----------- ---------------
                123         123               1
                234         345             234 <- Not a zero
                456         456               1
                  1           2               1 <- Not a match
        

        【讨论】:

          【解决方案6】:

          避免CASE WHEN 的解决方案是使用COALESCE

          SELECT
              t1.Col2 AS t1Col2,
              t2.Col2 AS t2Col2,
              COALESCE(NULLIF(t1.Col2, t2.Col2),NULLIF(t2.Col2, t1.Col2)) as NULL_IF_SAME
           FROM @t1 AS t1
          JOIN @t2 AS t2 ON t1.ColID = t2.ColID
          

          NULL_IF_SAME 列将为t1.col2 = t2.col2(包括NULL)的所有行提供NULL。 虽然这并不比CASE WHEN 表达式更具可读性,但它是ANSI SQL。

          只是为了好玩,如果想要布尔位值 0 和 1(虽然它不是很可读,因此不推荐),可以使用(适用于所有数据类型):

          1/ISNULL(LEN(COALESCE(NULLIF(t1.Col2, t2.Col2),NULLIF(t2.Col2, t1.Col2)))+2,1) as BOOL_BIT_SAME.
          

          现在,如果您有其中一种数字数据类型并且需要位,则在上面的 LEN 函数中首先转换为字符串,这可能会出现问题,因此这应该可以工作:

          1/(CAST(ISNULL(ABS(COALESCE(NULLIF(t1.Col2, t2.Col2),NULLIF(t2.Col2, t1.Col2)))+1,0)as bit)+1) as FAST_BOOL_BIT_SAME_NUMERIC
          

          以上内容适用于没有CAST 的整数。

          注意:同样在 SQLServer 2012 中,我们有 IIF 函数。

          【讨论】:

          • 就像你说的,这很难阅读(和维护)。最好告诉 OP 没有比使用 CASE 语句更简单的解决方案。 CASE 语句也是 ANSI 标准的一部分。
          【解决方案7】:

          我能想到的最接近的方法是NULLIF

          SELECT 
              ISNULL(NULLIF(O.ShipName, C.CompanyName), 1),
              O.ShipName,      
              C.CompanyName,
              O.OrderId
          FROM [Northwind].[dbo].[Orders] O
          INNER JOIN [Northwind].[dbo].[Customers] C
          ON C.CustomerId = O.CustomerId
          
          GO
          

          NULLIF 返回第一个表达式如果两个表达式不相等。如果表达式相等,NULLIF 返回第一个表达式类型的空值。

          因此,对于列相等的记录,上述查询将返回 1,否则返回 第一个表达式

          【讨论】:

          • 查看我的回答,开头是“关于 David Elizondo 的回答”。
          • 你是对的 Rob。 ISNULL 函数可能会给出误报。它应该返回与这两列值的上下文完全不同的东西。在我的示例中,我正在比较 varchar 列,因此返回值 int 1 没有问题。正如我所说,我的解决方案不会返回零 (0),但它会在列不相等时产生差异。如果他不想使用 CASE,这是我能想到的最接近的解决方案 :)
          猜你喜欢
          • 1970-01-01
          • 2016-03-06
          • 2014-09-20
          • 2021-05-23
          • 1970-01-01
          • 1970-01-01
          • 2013-08-18
          • 1970-01-01
          • 2014-04-20
          相关资源
          最近更新 更多