加入结果后的where子句

时间:2019-01-17 13:39:10

标签: sql-server

在加入之前,where子句似乎适用。加入后如何过滤结果?

我的数据为:

use devBoxDb
go
CREATE TABLE LeftTbl (Id int IDENTITY(1,1),
                      Title varchar(250),
                      Category varchar(250),
                      DateUpdated datetime2(7),
                      CONSTRAINT PK_LeftTbl PRIMARY KEY CLUSTERED (Id ASC));
go
insert into LeftTbl(Title,Category,DateUpdated) values
    ('it''s','Accessories','2019-01-02 15:01:03'),
    ('one','TVs','2018-12-13 11:03:46'),
    ('thing','Games','2016-07-17 19:27:23'),
    ('to','Cars','2017-01-12 14:15:17'),
    ('write queries','TVs','1970-01-01 00:00:00');
go
CREATE TABLE RightTbl  (Id int IDENTITY(1,1),
                        EntityId int,
                        DateModified datetime2(7),
                        Reason varchar(250),                        
                        CONSTRAINT PK_RightTbl PRIMARY KEY CLUSTERED (Id ASC));

go
insert into RightTbl(EntityId,DateModified,Reason) values
    (4,'2018-12-13 16:40:11','but'),
    (1,'2019-01-09 01:07:29','it''s another'),
    (7,'2019-01-03 13:13:20','to'),
    (2,'2019-01-17 22:41:34','get correct results')
go

LeftTbl:

Id | Title         | Category    | DateUpdated         |
---|---------------|-------------|---------------------|
1  | it's          | Accessories | 2019-01-02 15:01:03 |
2  | one           | TVs         | 2018-12-13 11:03:46 |
3  | thing         | Games       | 2016-07-17 19:27:23 |
4  | to            | Cars        | 2017-01-12 14:15:17 |
5  | write queries | TVs         | 1970-01-01 00:00:00 |

RightTbl:

Id | EntityId | DateModified         | Reason 
---|----------|----------------------|----------------------|
1  |  4       | 2018-12-13 16:40:11  | but                  |
2  |  1       | 2019-01-09 01:07:29  | it's another         |
3  |  7       | 2019-01-03 13:13:20  | to                   |
4  |  2       | 2019-01-17 22:41:34  | get correct results  |

和我的查询为:

select l.Id, 
       l.Title, 
       l.Category,
       (
           case
               when r.DateModified is null then l.DateUpdated
               when r.DateModified > l.DateUpdated then r.DateModified else l.DateUpdated 
           end 
       ) as DateUpdated
from leftTbl l 
left outer join rightTbl r
on l.Id = r.EntityId
where DateUpdated >= '2018-12-13'
      and DateUpdated < '2018-12-14'

预期:

Id | Title   | Category    | DateUpdated                   |
-----------------------------------------------------------|
4  | to      | Cars        | 2018-12-13 16:40:11.0000000   |

实际:

Id | Title   | Category    | DateUpdated                  |
----------------------------------------------------------|
2  | one     | TVs         | 2019-01-17 22:41:34.0000000  |

Result返回带有DateUpdated> to-date的记录,这使我得出结论:where过滤器发生在join之前。是这样还是我理智?加入后如何进行过滤?

3 个答案:

答案 0 :(得分:0)

如果您执行左联接并且where子句位于左联接表上,则需要将其上移到联接的一部分(如下所示),因为如果where子句中具有左联接表,则它在逻辑上是sql将其变成内部联接

select Id, 
       Title, 
       Category,
       (
           case
               when r.DateModified is null then l.DateUpdated
               when r.DateModified > l.DateUpdated then r.DateModified else l.DateUpdated 
           end 
       ) as DateUpdated

from leftT l 
left outer join rightT r l.Id = r.EntityId
    -- though not sure what table this is from so maybe add table identifier
    AND DateUpdated >= 'from-date'
    and DateUpdated < 'to-date'

答案 1 :(得分:0)

您的查询有问题。

  1. 您的表还包含DateUpdated字段,并且您为计算字段提供的名称也相同。在这种情况下,不考虑计算字段。

  2. 使用此。 (但是有机会提高性能)

    Select * from
    (
    select Id, 
       Title, 
       Category,
       (
           case
               when r.DateModified is null then l.DateUpdated
               when r.DateModified > l.DateUpdated then r.DateModified else 
             l.DateUpdated 
           end 
       ) as DateUpdated
    
    from leftT l 
    left outer join rightT r
    on l.Id = r.EntityId
    ) as tab
    where DateUpdated >= 'from-date'
      and DateUpdated < 'to-date'
    

答案 2 :(得分:0)

似乎可以完成以下任务。不太确定是否会对性能产生影响

select l.Id, 
       l.Title, 
       l.Category,
       (
           case
               when r.DateModified is null then l.DateUpdated
               when r.DateModified > l.DateUpdated then r.DateModified else l.DateUpdated 
           end 
       ) as DateUpdated
from leftTbl l 
left outer join rightTbl r
on l.Id = r.EntityId
where IIF(r.DateModified is null or r.DateModified < l.DateUpdated, l.DateUpdated, r.DateModified) 
       between '2018-12-13' and '2018-12-14 23:59:59.9999999'

结果:

Id | Title   | Category    | DateUpdated                   |
-----------------------------------------------------------|
4  | to      | Cars        | 2018-12-13 16:40:11.0000000   |