2016-11-09 47 views
0

我有两个tables右外连接与OR条件和空在where子句 - SQL SERVER

table1table2

我有一个查询,如下

select val1, val2 , val3 
FROM table1 
RIGHT OUTER JOIN 
table2 
on (table1.key = table2.key) 
AND (table2.val1 IN (select val1 from data where datadate between @stdate and @enddate) or (table2.val1= 0 and table2.val2 =5)) 
WHERE table2.key IS NULL 

此查询运行非常缓慢

所以,我试图去优化它下面的方式

with cte 
as 
(
select key 
from table2 
where 
(table2.val1 IN (select val1 from data where datadate between @stdate and @enddate) or (table2.val1= 0 and table2.val2 =5)) 
) 


select val1, val2 , val3 
FROM table1 
RIGHT OUTER JOIN 
cte 
on (table1.key = cte.key) 

WHERE cte.key IS NULL 

还有查询的性能没有太大的改善。所以我试图用CUL替换Union中的OR clause。它改进了查询performance但给出了不同的结果。

with cte 
as 
(
select key 
from table2 
Inner join data 
on (data.val1 = table2.val1) 
union 
select key 
from 
table2 where val1 = 0 and val = 5 

) 

select val1, val2 , val3 
FROM table1 
RIGHT OUTER JOIN 
cte 
on (table1.key = cte.key) 

WHERE cte.key IS NULL 

是否更换OR clauseUNION一个正确的方法?此外,在WHEREclauseNULL条件从LEFT table消除所有记录。那么,在Join期间添加OR子句会有什么影响?

+1

我不明白您的查询,第一,是什么是'AND(table2.val1(...'?它是没有意义的编译。第二,你从'data'选择'val1'是什么?只有1条记录从那里返回?在你的第三个查询中, “table1”去哪里了? – sagi

+0

你的UNION与其他人的查询不同,它选择加入data.val的所有记录1 = table2.val1,加上其他记录。在你的第一个查询中,ON条件使用一个AND,而不是OR - 所以它不能和我所见到的一样 – Cato

+0

@Sagi我错过了查询中的IN子句。数据表返回多条记录......我编辑了这个问题 – bmsqldev

回答

2

我会写的原始查询:

SELECT val1, val2, val3 
FROM table2 t2 LEFT JOIN 
    table1 t1 
    ON t1.key = t2.key AND 
     (t2.val1 IN (select val1 from data where datadate between @stdate AND @enddate) OR 
     (t2.val1 = 0 and t2.val2 = 5)) 
WHERE t2.key IS NULL; 

这样写的,查询比较奇怪。为什么?主要连接条件包括t2.key。当它是NULL时,则在t1中可能不匹配。因此,查询似乎是相当于是这样的:

SELECT val1, val2, val3 
FROM table2 t2 
WHERE (t2.val1 IN (select val1 from data where datadate between @stdate AND @enddate) OR 
     (t2.val1 = 0 and t2.val2 = 5) 
    ) AND 
     t2.key IS NULL; 

(注:根据在SELECT列从何而来,你可能需要使用NULL替换这些)

如果你说错在您的问题查询,那么你应该问问另一个问题与正确的查询。

+0

恰恰是当我看到查询时我在想什么。 –

+0

这实际上是一个报告的现有存储过程。我知道t2.key = NULL会消除所有的t2表行。但是,由于Join子句具有OR条件从t2表中获取数据,所以我很困惑。所以这个和OR条件和这个条款在这里没什么关系? – bmsqldev

+0

@bmsqldev。 。 。 '或'是'JOIN'上的第二个条件。 “关键”比较仍然是主要的比较。 –

1

我觉得你得到不同的结果,你有丢失的日期条件在WHERE条件:

select val1 from data where datadate between @stdate and @enddate 

试试下面的SQL:

with cte 
as 
(
select key 
from table2 
Inner join data 
on (data.val1 = table2.val1 and datadate between @stdate and @enddate) 
union 
select key 
from 
table2 where val1 = 0 and val = 5 

) 

select val1, val2 , val3 
FROM table1 
RIGHT OUTER JOIN 
cte 
on (table1.key = cte.key) 

WHERE cte.key IS NULL