正确使用SQL Intersect的方法

时间:2013-07-01 19:31:15

标签: sql sql-server-2008

我正在尝试为以下场景构建查询:

我有两个表 Table1 Table2

Table1 的主键如 T1Attr1 T1Attr2 等等。

对应于 Table1 中的每个主键,我可以从 Table2 获取一组属性,类似于 T2Attr1 T2Attr2 等等。

我正在尝试查询 Table1 属性所共有的属性,例如,如果输入是 T1Attr1 T1Attr2 ,结果应具有 Table2 的两个共同属性。随着输入参数的增加,结果会更少,因为普通的属性会更少。

我的查询与此类似:

Select indId, indName from indData where pId =1

intersect
Select indId, indName from indData where pId =2

intersect
Select indId, indName from indData where pId =3

查询工作正常但是当pId列表很大(大于100)时,jdbc驱动程序会抛出错误消息。

有人可以提供有关正确使用此查询的建议,还是提供更好的解决方法?

谢谢!

2 个答案:

答案 0 :(得分:3)

您可以使用此查询,但效率不如您所拥有的那样:

SELECT indId, indName 
FROM indData 
WHERE pId IN (1, 2, 3, ..., 100)
GROUP BY indId, indName
HAVING COUNT(DISTINCT pId) = 100 ;  -- the number of pId you are searching on

您也可以使用JOINs。也许这将导致更好的执行计划,而不会导致此错误。如果(indId, pId)上存在唯一约束,则这相当于您的查询:

SELECT a1.indId, a1.indName 
FROM indData AS a1
  JOIN indData AS a2
    ON a2.indId = a1.indId
  JOIN indData AS a3
    ON a3.indId = a1.indId 
  ...
  JOIN indData AS a100
    ON a100.indId = a1.indId
WHERE a1.pId = 1
  AND a2.pId = 2
  ...
  AND a100.pId = 100 ;

(pId, indID) INCLUDE (indName)上的索引有助于提高效率。

答案 1 :(得分:2)

Intersect不是做你想做的事的唯一方法。您的查询是“set-within-sets”查询的示例。 “set”是indid, indname对。 “内部集合”具有pid的所有三个值。

我提倡对这种类型的查询使用带有having子句的聚合,因为对于许多类型的条件,这是一种非常灵活的方法。在您的情况下,结果查询是:

select indid, indname
from indData
group by indid, indname
having SUM(case when pid = 1 then 1 else 0 end) > 0 and
       SUM(case when pid = 2 then 1 else 0 end) > 0 and
       SUM(case when pid = 3 then 1 else 0 end) > 0;

如果您在pid上有索引并且值相对较少,那么添加where pid in (1, 2, 3)可能会使查询在性能方面受益。