如果一个或多个列包含非空值,则返回Y / N的最有效方法是什么?

时间:2011-03-08 17:58:08

标签: sql-server null

如果一行中 n 列之一包含非空值,则返回CHAR(1)指示符Y / N的最简洁方法是什么?

在这种情况下,性能很重要,但不是主要考虑因素。

直截了当的方式似乎是:

SELECT      CASE WHEN (C.TerminatedDate IS NULL
                       AND C.SelfClosedDate IS NULL
                       AND ...)
                 THEN 'Y'
                 ELSE 'N' END AS 'OpenInd'

  FROM      Customers C

好奇,如果有更好的方法;了解COALESCE():

SELECT      CASE WHEN COALESCE (C.TerminatedDate, C.SelfClosedDate, ...) IS NULL
                 THEN 'Y'
                 ELSE 'N' END AS 'OpenInd'

  FROM      Customers C

有更好的方法吗?

数据库服务器是SQL Server 2008。

6 个答案:

答案 0 :(得分:4)

由于没有人提出建议,因此问题要求concise ..

对于相同的数据类型,直接COALESCE最好

coalesce(a,b,c,d) is not null

如果您要处理不同的数据类型,请尝试修改后的COALESCE

coalesce(LEFT(a,1),LEFT(b,1),LEFT(c,1)) is not null

样品:

create table abc (a int, b datetime, c varchar(max), d image)
insert into abc select 1, GETDATE(), '', null
insert into abc select 1, null, '', null
insert into abc select 1, null, '', 0x123123
insert into abc select null, null, '', 0x123123
insert into abc select null, GETDATE(), '', 0x123123
insert into abc select null, null, null, null
insert into abc select 88, GETDATE()+3, null, null
insert into abc select 88, GETDATE()+3, 'gdasdf', null
insert into abc select null, null, '222', 0x123123
insert into abc select null, null, 'abcdef', 0x123123

select *, case when coalesce(LEFT(a,1),LEFT(b,1),LEFT(c,1)) is not null then 'N' else 'Y' end
from abc

如果您没有使用VARCHAR(MAX)或IMAGE等外来类型,那么您可以将SQL_VARIANT与COALESCE一起使用

create table abc (a int, b datetime, c varchar(10), d image)
insert into abc select 1, GETDATE(), '', null
insert into abc select 1, null, '', null
insert into abc select 1, null, '', 0x123123
insert into abc select null, null, '', 0x123123
insert into abc select null, GETDATE(), '', 0x123123
insert into abc select null, null, null, null
insert into abc select 88, GETDATE()+3, null, null
insert into abc select 88, GETDATE()+3, 'gdasdf', null
insert into abc select null, null, '222', 0x123123
insert into abc select null, null, 'abcdef', 0x123123

select *, case when coalesce(convert(sql_variant,a),b,c) is not null then 'N' else 'Y' end
from abc

答案 1 :(得分:3)

理论上,当任何值不为空时,你应该通过立即返回来获得短路的优势

Select Case
        When C.TerminatedDate Is Not Null Then 'N'
        When C.SelfClosedDate Is Not Null Then 'N'
        ...
        Else 'Y'
        End

尽管如此,我怀疑此解决方案与您的上述解决方案之间的性能存在显着差异(假设您可以使用Coalesce)。

答案 2 :(得分:3)

这是一个“开箱即用”的解决方案。一个持久的计算列。

CREATE TABLE [dbo].[Customer](
  [CustomerID] [int] IDENTITY(1,1) NOT NULL,
  [Date1] [datetime] NULL,
  [Date2] [datetime] NULL,
  [AllNulls]  AS (case when [date1] IS NULL AND [date2] IS NULL then 'Y' else 'N' end) PERSISTED NOT NULL,
 CONSTRAINT [PK_Cusomter] PRIMARY KEY CLUSTERED 
 (
    [CustomerID] ASC
 )
)

答案 3 :(得分:2)

如果没有进一步的信息,前者(案例陈述)是MS SQL Server中最有效的方法。 (虽然使用相同的假设,我个人会将其作为一个值返回并执行转换为Y / N,这实际上是显示表示或视图模型的关注。)

现在,如果要重复进行过滤,并且出于性能原因,在数据库引擎上这样做是合适的,在where子句中执行NULL测试会进一步改进。如果你有很多这些,你可以考虑在更新时聚合它们(通过另一个回答者,存储过程,数据模型或天堂禁止触发的精美建议的持久计算列)。

答案 4 :(得分:1)

如果所有列都是日期时间,则除非总溢出,否则这将起作用。注意零= 1900年1月1日所以在9999年12月31日之前有很多空间

NULL添加到任何其他表达式给出NULL

SELECT
    CASE
         WHEN C.TerminatedDate + C.SelfClosedDate + C.OtherDate + .. IS NULL THEN
                 THEN 'Y'
                 ELSE 'N'
         END AS 'OpenInd'

  FROM      Customers C

答案 5 :(得分:1)

简洁的合并方法肯定会损害性能的一种情况是处理离线数据,这也需要隐式转换。

CREATE TABLE coalescetest
(
id int identity(1,1) PRIMARY KEY,
bigvarchar1 varchar(max) NULL,
bigvarchar2 varchar(max) NULL,
bignvarchar1 Nvarchar(max) NULL,
bignvarchar2 Nvarchar(max) NULL
)

INSERT INTO coalescetest
SELECT TOP 100
     REPLICATE(CAST('A' AS VARCHAR(MAX)),12000),
     REPLICATE(CAST('A' AS VARCHAR(MAX)),12000),
     REPLICATE(CAST('A' AS NVARCHAR(MAX)),12000),
     REPLICATE(CAST('A' AS NVARCHAR(MAX)),12000)   
FROM master..spt_values             

SET STATISTICS IO ON    

SELECT      id, CASE WHEN COALESCE (bigvarchar1,bigvarchar2,bignvarchar1,bignvarchar2) IS NULL
                 THEN 'Y'
                 ELSE 'N' END AS Result

FROM coalescetest

给出

  

表'coalescetest'。扫描计数1,逻辑读取5,物理读取0,   预读读取0,lob逻辑读取 400 ,lob物理读取0,   lob预读读取 300

SELECT      CASE WHEN (bigvarchar1 IS NULL
                       AND bigvarchar2 IS NULL
                       AND bignvarchar1 IS NULL
                       AND bignvarchar2 IS NULL)
                 THEN 'Y'
                 ELSE 'N' END AS Result
  FROM     coalescetest

给出

  

表'coalescetest'。扫描计数1,   逻辑读取5,物理读取0,   预读读取0,lob逻辑读取    0 ,lob物理读取0,lob   预读读取 0