Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于在排除一组行的同时检索数据的SQL查询_Sql - Fatal编程技术网

用于在排除一组行的同时检索数据的SQL查询

用于在排除一组行的同时检索数据的SQL查询,sql,Sql,我基本上有四个SQL Server表: Objects: id ObjectName Components id ComponentName ObjectsDetails: ObjectID ComponentID ExclusionTable id ComponentID 基本上,这些表描述了对象以及哪些对象由哪些组件组成 例如,对象A可以由组件A和组件B构成 在这种情况下,表将以以下方式填充: 对象: id对象名 1A 组成部分: id组件名称 1A 2 B 对象详细信息: Obje

我基本上有四个SQL Server表:

Objects:
id
ObjectName

Components
id
ComponentName

ObjectsDetails:
ObjectID
ComponentID

ExclusionTable
id
ComponentID
基本上,这些表描述了对象以及哪些对象由哪些组件组成

例如,对象A可以由组件A和组件B构成

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

对象: id对象名 1A

组成部分: id组件名称 1A 2 B

对象详细信息: ObjectID组件 1 1 1 2

现在,ExclutionTable可能有一个要从搜索中排除的组件列表,因此,如果对象由至少一个组件组成,则排除整个对象

例如,我想问:

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

因此,我的问题是:

有没有一种方法可以为此编写查询?请不要查看,不要存储过程。。我的SQL引擎不支持这一点

我试过这样的方法:

SELECT DISTINCT ObjectName FROM Objects INNER JOIN ObjectsDetails ON Objects.id =    
ObjectDetails.ObjectID WHERE ObjectsDetails.ComponentID NOT IN (1,2)
如果排除表告诉我们需要排除组件A和B

当然,这是行不通的

我尝试了一些使用WHERE NOT EXISTS SELECT*FROM ExclusionTable的变体,但我对SQL不够精通,无法理解如何仅在可能的情况下使用一个查询使其工作


谢谢

基本上,如果需要获取非由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子句中过滤掉。

您应该避免在select中使用[not]进行查询

这将仅检索组件ID不在表中的行

更新:

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)
新的方法,我认为我能做的唯一其他方法基本上是比较每个对象的组件数量和列表中未包含的对象中的组件数量。当这些数字相等时,排除列表中没有组件,我们可以显示对象

很抱歉,我现在无法进行测试,请使用解释选择。。。若查询有效,则比较查询。

选择id、objectname 来自对象 左外连接 从ObjectsDetails od内部联接排除表et中选择objectid 在od.ComponentID=et.ComponentID excludedid上
在Objects.ID=excludedid.ObjectID和excludedid.ObjectID为null时

您声明要排除组件,但排除表中有ObjectID,而不是ComponentId。。。这是一个打字错误,还是故意的?嗨,这是一个打字错误;对此我很抱歉。正如您所说,它应该是组件化的。没错,从性能的角度来看,这是一个更好的解决方案。您好,谢谢您的帮助。不幸的是,查询返回所有对象。我有一个包含4个对象的测试数据库:a、B、C和D。类似地,有4个组件:CA、CB、CC、CD。对象A由CA,CB组成,对象B由CA,CD组成,对象C由CC,CD组成,对象D由CB,CD组成。排除表包含组件CA和CC。因此,查询应该只返回对象D,因为它既不是由CA也不是由CC组成,而其他查询则至少由排除表中包含的一个对象组成。但是,查询将返回所有对象。再次感谢!我仍然有兴趣找到一个性能友好的解决方案。因此,我做了一些测试,您的查询至少在逻辑上是正确的。例如,如果我将WHERE子句更改为WHERE EXCLUSTIONTABLE.ComponentID不为NULL,则除D之外的所有对象都将显示预期的行为。但是,如果保持原样,将显示所有对象。我甚至试图在排除表中插入一个空值,但这也没有帮助。你知道为什么它不起作用吗?谢谢。不幸的是,此查询返回所有对象。
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)