Sql server SQL连接:输入,输出,到处摇晃
我正在执行下面的sql来返回一个数据,其中表1和表2中的dob和address都匹配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
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
(按该顺序!),它也会加快分组/排序操作。