将not in子句更改为inner join

时间:2014-09-02 13:41:49

标签: sql sql-server

如何将以下查询转换为内部联接,并避免使用distinct来优化性能。

select distinct(GroupId) 
from   BatchQuotaIndividualQuotas 
where  BatchQuotaCommonSettingsID = 58 
       and 
       GroupId not in 
       (
           select distinct(groupid) 
           from   BatchQuotaIndividualQuotas 
           where  BatchQuotaCommonSettingsID = 58 
                  and ObjectiveFunctionTotalResultID is null 
       )

GroupId不是主键。有多个行对应于单个GroupId。我想选择没有ObjectiveFunctionTotalResultID为null的GroupIds。 -

4 个答案:

答案 0 :(得分:2)

首先,distinct不是函数,而是select语句的修饰符。您可以选择不同的字段值组合,而不是选择不同的单个字段。如果您有更多字段,则括号实际上会调用语法错误。所以它不是

select
  distinct(groupid)

select distinct
  groupid   

其次,你根本不需要内在的区别。 in列表中可能存在重复项,dbms可能已经为您优化了这一点。通过在内部查询中添加distinct,您可以主动阻止优化器完成其工作。

第三,如果您想拥有不同的组ID,则仍需要distinct外部查询。内部联接不会改变这一点。此外,由于您希望记录必须匹配,因此内连接不会起作用。左连接可以执行此操作,但如果我正确解释您的查询,您可以将其写为:

select distinct
  GroupId
from 
  BatchQuotaIndividualQuotas 
where 
  BatchQuotaCommonSettingsID = 58 and 
  ObjectiveFunctionTotalResultID is not null

可以将其改为group by,就像我在下面所做的那样,但效果是一样的。分组只创建组,并且还必须删除重复项。分组主要用于聚合。我不确定内部工作原理,但group by在理论上是一个更难的过程,因为数据库需要为这些聚合创建实际的组,而不是仅仅过滤掉重复项。可能这也会被优化,所以最后,下面的查询将执行和行为与上面的相同。

select
  GroupId
from 
  BatchQuotaIndividualQuotas 
where 
  BatchQuotaCommonSettingsID = 58 and 
  ObjectiveFunctionTotalResultID is not null
group by
  GroupId

答案 1 :(得分:2)

您可以使用LEFT JOIN获得类似的结果,然后将联接结果设置为NULL

select distinct GroupId
from   BatchQuotaIndividualQuotas A
left join BatchQuotaIndividualQuotas B ON B.ObjectiveFunctionTotalResultID IS NULL 
                                      AND B.GroupId = A.GroupId
                                      AND B.BatchQuotaCommonSettingsID = 58
where  A.BatchQuotaCommonSettingsID = 58
   AND B.GroupId IS NULL

您也可以使用GROUP BYHAVING获得相同的结果,但我怀疑这种方法会更快。

select GroupId
from   BatchQuotaIndividualQuotas 
where  BatchQuotaCommonSettingsID = 58
group by GroupId
having SUM(CASE WHEN ObjectiveFunctionTotalResultID IS NULL THEN 1 ELSE 0 END) = 0

答案 2 :(得分:1)

如果从where子句中删除distinct,则查询将运行得更快。

以下是两种更好的写作方式

count(ObjectiveFunctionTotalResultID)将计算非空值

SELECT GroupId
FROM   BatchQuotaIndividualQuotas 
WHERE  BatchQuotaCommonSettingsID = 58 
GROUP BY GroupId
HAVING count(ObjectiveFunctionTotalResultID) = count(*)

或:

EXCEPT将包含不同的

SELECT GroupId
FROM   BatchQuotaIndividualQuotas 
WHERE  BatchQuotaCommonSettingsID = 58 
EXCEPT
SELECT GroupId
FROM   BatchQuotaIndividualQuotas 
WHERE  BatchQuotaCommonSettingsID = 58 
AND ObjectiveFunctionTotalResultID is null

答案 3 :(得分:0)

你能试试吗?

select GroupId
from   BatchQuotaIndividualQuotas 
where  BatchQuotaCommonSettingsID = 58 
and ObjectiveFunctionTotalResultID  IS NOT NULL
GROUP BY GroupId

相同的查询(如果我是正确的)有一些修改后的流程。它不是通过子查询过滤掉ID,而是在适当的位置完成。