替换WHERE子句中的ISNULL函数

时间:2018-01-02 09:14:06

标签: sql sql-server sql-server-2008 tsql

由于性能问题,我被要求通过消除where子句中的$this->Model->find() ->where(['rght - lft =' => 1]); 函数来重写以下查询。如何通过替换ISNULL子句和ISNULL条件中的WHERE函数来重写以下查询。以下是示例查询。

JOIN

6 个答案:

答案 0 :(得分:2)

在大多数情况下,您只需删除dBm功能,就不需要替换任何内容。例如:

isnull

可以改写为

select * 
from parent 
where isnull(Status, '') != 'Active'

由于select * from parent where Status != 'Active' 为空,比较仍会返回Status。规则是: NULL = value:NULL(解释为FALSE,因为它不是TRUE)。

如果结果中必须包含NULL,则可以添加FALSE

答案 1 :(得分:2)

Select * from child c inner join Parent P on c.id=p.id where ISNULL(p.ParentId, 0) <> 0

在这里,您既不需要ISNULL也不需要替代,因为在这种情况下

NULL <> 0同样FALSE 0 <> 0FALSE

如果设置NULL = NULL其他FALSE

SET ANSI_NULLS ON将为TRUE

在这里,替代方案是,

如果您想将NULL作为TRUE返回,则可以使用

WHERE (p.ParentId IS NULL OR p.ParentId <> 0)

否则,

(p.ParentId <> 0 OR 0 <> 0) --But it doesn't have any meaning and it's exactly same to simply use p.ParentId <> 0

您可以在所有问题中相应地处理ISNULL

答案 2 :(得分:2)

小心这一点 看看这个例子:

declare @table table(ID int, status varchar(50))

insert into @Table (ID, status)
values (1, 'active'), (2, ''), (3, null), (4, 'active')

select t.*
from   @Table t
where  t.status <> 'active'

这将只返回一条记录(ID:2)

虽然这个

select t.*
from   @Table t
where  isnull(t.status, '') <> 'active'

将返回2条记录(ID:2和3)

所以这取决于你在结果集中想要什么,你是否想要也返回字段Status为null的记录?
如果您不想要它们,那么答案很简单

select t.*
from   @Table t
where  t.status <> 'active'

否则你需要这样的东西
由于原始查询中包含IsNull,我怀疑这是你想要的。

select t.*
from   @Table t
where (t.status is null or t.status <> 'active')

这不使用IsNull(),但我不确定这里是否会获得很多性能。

答案 3 :(得分:0)

请尝试这样。

Select * from child c inner join Parent P 
on c.id=p.id OR where p.ParentId IS NULL

Select * from child c inner join Parent P on c.Parentid=p.id OR c.ParentId IS NULL

select * from parent 
where [Status] != 'Active' AND [Status] IS NOT NULL

Select * from child c inner join Parent P on c.id=p.id 
where 
    ( (P.PostedDate) BETWEEN CAST(@FromDate) AS DATE) AND @FromDate IS NOT NULL  AND CAST(@ToDate AS DATE) )
OR 
    ( (P.PostedDate) BETWEEN P.PostedDate AND CAST(@ToDate AS DATE) )

SELECT * FROM TEMP 
WHERE EDATE = CASE WHEN @EDATE IS NULL THEN EDATE ELSE @EDATE END 

答案 4 :(得分:0)

替换如下以制定SARGABLE:

    where ISNULL(p.ParentId, 0) <> 0 --- where p.ParentId = 0 or p.ParentID is null
    Select * from child c inner join Parent P on isnull(c.Parentid,0)=p.id --- Select * from child c inner join Parent P on c.Parentid = p.id OR (c.Parentid is null and p.id = 0)
    where isnull(Status, '') != 'Active' --- where Status <> 'Active'
    where CAST(P.PostedDate AS DATE) BETWEEN CAST(isnull(@FromDate,P.PostedDate) AS DATE) AND CAST(@ToDate AS DATE) --- where P.PostedDate BETWEEN isnull(@FromDate,P.PostedDate) AND @ToDate
    WHERE EDATE=ISNULL(@EDATE,EDATE) --- WHERE @EDATE IS NULL OR EDATE = @EDATE

答案 5 :(得分:0)

当值可以为null时,您必须使用三值逻辑。 Read this article. 因此,如果你想让你的参数SARGABLE避免使用ISNULL或COALESCE函数,你必须结合OR / AND / NOT / CASE运算符,具体取决于查询的逻辑

在您的示例中:

 <Target Name="DebugRunWebpack" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('wwwroot\dist') ">
    ....

    <Exec Command="node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js" />
    <Exec Command="node node_modules/webpack/bin/webpack.js" />
  </Target>