SQL Query在排除一组行的同时检索数据

时间:2010-08-11 22:46:16

标签: sql

我基本上有四个表(SQL Server):

Objects:
id
ObjectName

Components
id
ComponentName

ObjectsDetails:
ObjectID
ComponentID

ExclusionTable
id
ComponentID

基本上,这些表描述了对象和对象是由什么组成的(哪些组件)

例如,对象“A”可以由组件“A”和组件“B”组成。

在这种情况下,表格将以这种方式填充:

物件:
id ObjectName
1 A

组件:
id ComponentName
1 A
2 B

ObjectDetails:
ObjectID组件ID
   1 1
   1 2

现在,“ExclusionTable”可能有一个要从搜索中排除的组件列表(因此,如果对象是由至少一个组件构成的,则排除整个对象)。

例如,我想问:

“给我所有不是由组件A和B组成的对象”。

因此,我的问题是:

有没有办法为此编写查询?没有视图,没有存储过程请...我的SQL引擎不支持。

我尝试过类似的事情:

SELECT DISTINCT ObjectName FROM Objects INNER JOIN ObjectsDetails ON Objects.id =    
ObjectDetails.ObjectID WHERE ObjectsDetails.ComponentID NOT IN (1,2)

如果ExclusionTable告诉我们需要排除组件A和B.

当然,这不起作用......

我尝试了一些使用WHERE NOT EXISTS(SELECT * FROM ExclusionTable)的变体,但我不熟练使用SQL来了解如何仅使用一个查询(如果可能的话)使其工作。

谢谢!

3 个答案:

答案 0 :(得分:1)

您应避免使用[not] in (select ...)

进行查询
SELECT DISTINCT ObjectName 
FROM Objects 
INNER JOIN ObjectsDetails ON Objects.id = ObjectDetails.ObjectID 
LEFT JOIN ExclusionTable on ExclusionTable.ComponentId = ObjectsDetails.ComponentID
where ExclusionTable.ComponentId is null;

这将只检索ComponentID不在ExclusionTable中的行。

更新

SELECT ObjectName 
FROM Objects
INNER JOIN ObjectsDetails ON Objects.id = ObjectDetails.ObjectID 
LEFT JOIN ExclusionTable on ExclusionTable.ComponentId = ObjectsDetails.ComponentID
group by ObjectName 
having count(distinct ObjectsDetails.ComponentID) = sum(case when ExclusionTable.id is null then 1 else 0 end)

新方法,我认为我能做到的唯一其他方法基本上是将每个对象的组件数量与列表中未包含的对象中的组件数量进行比较。当这些数字相等时,排除列表中没有任何组件,我们可以显示该对象。

对不起,我现在无法进行测试,如果查询有效,请使用EXPLAIN select ...来比较查询。

答案 1 :(得分:0)

基本上,如果你需要获得所有不是由A或B制作的对象,你需要获得除A或B之外的所有对象。

SELECT DISTINCT Id, ObjectName 
FROM Objects 
WHERE Id NOT IN (
SELECT DISTINCT ObjectDetails.ObjectID 
FROM ObjectDetails
INNER JOIN Components ON ObjectDetails.ComponentID = Components.Id
WHERE Components.ComponentName = 'A' OR Components.ComponentName = 'B'
)

这会是你想要的吗?

编辑:当然,如果您已经拥有组件ID,则可以省略连接 - 然后将它们放在where子句中以过滤掉它们。

答案 2 :(得分:0)

选择id,objectname 来自Objects 左外连接 (从ObjectsDetails od内部连接Exclusiontable等选择objectid on od.ComponentID = et.ComponentID)excludedid on Objects.ID = excludedid.ObjectID和excludedid.ObjectID为null