为什么这两个sql查询的输出不同?

时间:2010-11-16 18:02:35

标签: sql mysql

两张桌子:
a)svn3name revno compname
b)archdetailsname version compname inFlat

这两个查询不应该输出相同的结果。查询2的输出是正确的。 query1有什么问题?

QUERY1:
select sum(CASE WHEN inFlat=1 THEN 1 ELSE 0 END) from archdetails inner join svn3 on archdetails.compname=svn3.compname where archdetails.name='ant' AND version='1.4' AND (revno='r274642' OR revno='r274578' OR revno='r274533')

QUERY2:
select sum(CASE WHEN inFlat=1 THEN 1 ELSE 0 END) from archdetails where name='ant' AND version='1.4' AND compname IN (select compname from svn3 where revno ='r274642' OR revno='r274578' OR revno='r274533')

3 个答案:

答案 0 :(得分:2)

如果svn3的多个行具有相同的compname并且还有一个请求的revno值,则查询1将对每个svn3行计算一次。查询2仅计算每个compname一次。 IN子句消除了第二个查询中的任何重复compname条目。

如果您不想计算重复的compname条目,则需要将它们分组到子查询中。一种方法是使用IN子句,就像在查询2中一样。另一种选择是在子查询上使用GROUP BY,并命名该子查询。然后将命名子查询加入archdetails表。

如果您正在尝试解决性能问题,那么我建议将主键和外键添加到表中。我认为这会加快速度。

我看到一些评论EXISTS有时比IN更快,但我没有看到任何证据支持这一点。您可能想要尝试一下。

答案 1 :(得分:2)

不,两个查询不一样 - 第一个查询加入compname上的svn3记录,版本'1.4'和3个revno值之一。如果给定的compname存在多个svn3记录(版本为'1.4'且任何3 revno值),则query1将返回更多结果。

可能的解决方案:改变

sum(CASE WHEN inFlat=1 THEN 1 ELSE 0 END)

count(distinct CASE WHEN inFlat=1 THEN archdetails.compname END)

(假设archdetails.compname唯一标识要在此查询中计算的每个archdetails记录,并给出其中的其他约束。)

答案 2 :(得分:0)

看过其他答案之后,我现在认为这是一个不太可能的解释,但如果不是......会保留它......

我的猜测是,这是由某处的NULL值引起的(将其归咎于NULL是一种通常有效的策略)。是archdetails.compname还是svn3.compname可以为空,如果是,那么这些表中是否包含空值?如果确实存在空值,则需要确定在比较空值时确切想要发生的事情。

如果它是由空值引起的,那么您的ANSI_NULLS设置也可能在此处发挥作用。