Sql 将not in子句更改为内部联接

Sql 将not in子句更改为内部联接,sql,sql-server,Sql,Sql Server,如何将以下查询转换为内部联接并避免使用distinct来优化性能 select distinct(GroupId) from BatchQuotaIndividualQuotas where BatchQuotaCommonSettingsID = 58 and GroupId not in ( select distinct(groupid) from BatchQuotaIndivid

如何将以下查询转换为内部联接并避免使用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均不为空的GroupId

你能试试这个吗

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

同样的问题,如果我对一些修改后的流程是正确的。它没有通过子查询过滤出ID,而是就地进行过滤。

您能试试这个吗

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

同样的问题,如果我对一些修改后的流程是正确的。它不是通过子查询过滤出ID,而是就地过滤。

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

select
  distinct(groupid)
但是

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

第三,如果您想要拥有不同的组ID,那么您仍然需要在外部查询上使用distinct。内部联接不会改变这一点。此外,由于您希望有不匹配的记录,因此内部联接不能起作用。左连接可以做到这一点,但如果我正确解释您的查询,您可以将其编写为:

select distinct
  GroupId
from 
  BatchQuotaIndividualQuotas 
where 
  BatchQuotaCommonSettingsID = 58 and 
  ObjectiveFunctionTotalResultID is not null
你可以像我在下面所做的那样将其更改为“分组方式”,但效果是一样的。GROUPBY只创建组,还必须删除重复项。Group by主要用于聚合。我不确定内部的工作方式,但理论上分组是一个比较困难的过程,因为数据库需要为这些聚合创建实际的组,而不仅仅是过滤掉重复的组。可能这也会得到优化,因此最终,下面的查询将执行与上面的查询相同的操作

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

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

select
  distinct(groupid)
但是

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

第三,如果您想要拥有不同的组ID,那么您仍然需要在外部查询上使用distinct。内部联接不会改变这一点。此外,由于您希望有不匹配的记录,因此内部联接不能起作用。左连接可以做到这一点,但如果我正确解释您的查询,您可以将其编写为:

select distinct
  GroupId
from 
  BatchQuotaIndividualQuotas 
where 
  BatchQuotaCommonSettingsID = 58 and 
  ObjectiveFunctionTotalResultID is not null
你可以像我在下面所做的那样将其更改为“分组方式”,但效果是一样的。GROUPBY只创建组,还必须删除重复项。Group by主要用于聚合。我不确定内部的工作方式,但理论上分组是一个比较困难的过程,因为数据库需要为这些聚合创建实际的组,而不仅仅是过滤掉重复的组。可能这也会得到优化,因此最终,下面的查询将执行与上面的查询相同的操作

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

使用左连接,然后将连接结果设置为NULL,可以获得类似的结果

您也可以通过GROUP BY和Have获得相同的结果,尽管我怀疑这种方法会更快

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

使用左连接,然后将连接结果设置为NULL,可以获得类似的结果

您也可以通过GROUP BY和Have获得相同的结果,尽管我怀疑这种方法会更快

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

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

这里有两种更好的写作方法

countObjectiveFunctionTotalResultID将计数非空值

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

除此之外,将包括不同的

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

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

这里有两种更好的写作方法

countObjectiveFunctionTotalResultID将计数非空值

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

除此之外,将包括不同的

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

这无法正常工作,因为GroupId不是主键。有多行对应于单个GroupId。我想选择ObjectiveFunctionTotalResultID均不为空的GroupId。这无法正常工作,因为GroupId不是主键。有多行对应于单个GroupId。我想选择ObjectiveFunctionTotalResultID均不为空的GroupId。您的答案不正确,原因与Alex的回答中所述的相同,说明了添加表结构、问题键等信息的重要性:我看看我能做些什么。看看,你可以用
一个左连接,在我的-尽管是-回答查询之前我已经简要地提到过。但是@Dan已经在他的答案中找到了解决方案,所以你可以选择他的答案除了我发布了2个更好的答案,这不是意见的问题,而是性能和可读性的问题。这不是哲学,你的答案不正确,原因与Alex的回答中所述的相同,说明了添加表结构、问题关键等信息的重要性我来看看我能做些什么。看一看,你可以用一个左连接来解决它,我在我的-尽管是-答案查询之前已经简要地提到了。但是@Dan已经在他的答案中找到了解决方案,所以你可以选择他的答案除了我发布了2个更好的答案,这不是意见的问题,而是性能和可读性的问题。这不是哲学