Sql server SQL连接:输入,输出,到处摇晃

Sql server SQL连接:输入,输出,到处摇晃,sql-server,join,inner-join,outer-join,Sql Server,Join,Inner Join,Outer Join,我正在执行下面的sql来返回一个数据,其中表1和表2中的dob和address都匹配 select table1.dob , table1.address , sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count' , sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count' , sum(case when

我正在执行下面的sql来返回一个数据,其中表1和表2中的dob和address都匹配

select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count' 
from table1
inner join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > @myDate
group by table1.dob, table1.address
order by table1.dob, table1.address
然而,当表2中没有匹配项时,我现在想从表1返回数据,并且只返回该数据,我认为简单地将内部连接更改为左外部连接将执行我所需的操作,但事实并非如此


谢谢

在这种情况下,如果不是联接,则应使用函数。

在这种情况下,如果不是联接,则应使用函数。

如果联接中没有匹配项,则第二个表中的字段为空,因此必须检查表2中的空值。假设表2中的dob不为空,这将解决您的问题:

select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count' 
from table1
left outer join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > @myDate and table2.dob is null
group by table1.dob, table1.address
order by table1.dob, table1.address

如果联接中没有匹配项,则第二个表中的字段为NULL,因此必须在表2中检查NULL值。假设表2中的dob不为空,这将解决您的问题:

select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count' 
from table1
left outer join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > @myDate and table2.dob is null
group by table1.dob, table1.address
order by table1.dob, table1.address

您也可以在此处使用EXCEPT关键字

select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count' 
from table1
where table1.dob > @myDate
EXCEPT
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count' 
from table1
inner join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > @myDate

这将获得第一个查询中不在第二个查询中的所有记录。

您也可以在此处使用EXCEPT关键字

select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count' 
from table1
where table1.dob > @myDate
EXCEPT
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count' 
from table1
inner join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > @myDate

这将获得第一个查询中不在第二个查询中的所有记录。

在我看来,LEFT-JOIN更干净,如果LEFT-JOIN的性能与not-EXISTS之间没有太大差异,您应该使用它@JNK说,“存在和不存在通常比加入或其他类似的运营商更快,因为他们短路-第一次击中他们就进入下一个条目”,但我的理解是,NOT EXISTS和NOT IN通常成本很高,因为sql server必须检查查找表中的所有记录,以确保条目实际上不存在,因此,我不知道短路是如何工作的

在我看来,左连接要干净得多,如果左连接的性能与不存在的性能之间没有太大差异,您应该这样做@JNK说,“存在和不存在通常比加入或其他类似的运营商更快,因为他们短路-第一次击中他们就进入下一个条目”,但我的理解是,“不存在”和“不在”通常都很昂贵,因为sql server必须检查查找表中的所有记录,以确保条目实际上不存在,因此我不知道短路会如何工作

谢谢!子查询通常比较慢,因此添加null值(正如@il_guru所建议的)会更快?服务器将子查询和联接转换为一组类似的执行步骤。还要注意“过早优化”!您应该在发现查询速度慢之后才开始考虑优化查询,当然,当查询仍在生成错误的结果集时,请不要费心。现在,它不会生成错误的结果集。然而,它将在上亿条记录上运行。所以我需要优化它。谢谢!子查询通常比较慢,因此添加null值(正如@il_guru所建议的)会更快?服务器将子查询和联接转换为一组类似的执行步骤。还要注意“过早优化”!您应该在发现查询速度慢之后才开始考虑优化查询,当然,当查询仍在生成错误的结果集时,请不要费心。现在,它不会生成错误的结果集。然而,它将在上亿条记录上运行。所以我需要优化它。谢谢!你认为这种方法会比用子查询重写更快,而且不存在吗?我不确定性能问题。。。我在谷歌上搜索了一下,没有确切的结论,这也取决于你的数据库结构和索引。从执行计划来看,“不存在”方式似乎消耗较少的CPU,但它似乎更为I/O密集,并且可能会出现需要获取数百万条记录的问题。查看此链接,注释@NimChimpsky-
存在
不存在
通常比连接或其他操作符(如中的
)更快,因为它们短路-第一次点击时,它们会转到下一个条目。谢谢!你认为这种方法会比用子查询重写更快,而且不存在吗?我不确定性能问题。。。我在谷歌上搜索了一下,没有确切的结论,这也取决于你的数据库结构和索引。从执行计划来看,“不存在”方式似乎消耗较少的CPU,但它似乎更为I/O密集,并且可能会出现需要获取数百万条记录的问题。查看此链接,注释@NimChimpsky-
EXISTS
NOT EXISTS
通常比join或其他操作符(如
中的
)更快,因为它们会短路-第一次点击时,它们会转到下一个条目。仅供参考,根据您关于调整性能的注释,检查您的索引!您当然希望在dob字段上有一个索引,可能还需要person_状态和地址。如果您在
Dob,Address
(按该顺序!)上放置一个覆盖索引,它也会加快您的分组/排序操作。仅供参考,根据您关于调整性能的评论,检查您的索引!您当然希望在dob字段上有一个索引,可能还需要person_状态和地址。如果你把一个覆盖索引放在
Dob,Address
(按该顺序!),它也会加快分组/排序操作。