外部自联接过滤器与子查询

bjo*_*sig 4 join sql-server subquery sql-server-2012

我有一张表存储有关门票的信息。售票时有一个记录,使用票时有另一个记录。有一个名为 TransType 的列,它被设置为“已售出”或“已使用”以标记它是哪一个。表中还有其他列,其中一些列在销售时包含值,但在使用时不包含值,反之亦然。该表实际上是数据仓库风格的事实表。

在其他事情中,我正在计算销售和使用之间的时间差,因此我将表格加入到自己的表格中,以便为每张票获取一条记录,以便能够在同一记录中计算两个事件的时间戳。

我需要包括所有售出的门票,所以外连接应该可以解决这个问题。

首先我运行了这个查询

select x.* 
from factI as x
left join factI as y on x.tickedId = y.tickedId
where x.TransType = 'sold'
and y.TransType = 'used'
Run Code Online (Sandbox Code Playgroud)

当我运行它时,过滤器 x.TransType = 'sold' 不起作用,并且查询实际上返回所有记录的结果,无论 TransType 是什么。如果我使用内连接,这会起作用,但显然不会返回尚未使用的票证。

所以我将查询更改为这个给我正确结果的查询。

select * from (
   select * from factI where TransType = 'sold'
) as x
left join (
   select * from factI where TransType = 'used'
) as y on x.ticketId = y.ticketId
Run Code Online (Sandbox Code Playgroud)

当我使用外部(左)连接时,为什么第一个查询中的 where 子句没有正确过滤掉?

ype*_*eᵀᴹ 10

您的第一个查询是inner join因为y.TransType = 'used'使用正确表的条件在where子句中。

只需将该条件移动到on子句,就可以在没有派生表的情况下重写您的第二个查询:

select x.*, y.*
from factI as x
left join factI as y on  x.tickedId = y.tickedId
                     and y.TransType = 'used'
where x.TransType = 'sold' ;
Run Code Online (Sandbox Code Playgroud)