SQL-选择其他表中不存在的记录(3表关系)

SQL-选择其他表中不存在的记录(3表关系),sql,sql-server,Sql,Sql Server,我有三张桌子: Table_Cars -id_car -description Table_CarDocuments -id_car -id_documentType -path_to_document Table_DocumentTypes -id_documentType -description 我想选择表中没有文档的所有车辆。表中有4个特定id的文档 大概是这样的: Car1 | TaxDocument Car1 | KeyDocument Car2 | TaxDocument

我有三张桌子:

Table_Cars
-id_car
-description

Table_CarDocuments
-id_car
-id_documentType
-path_to_document

Table_DocumentTypes
-id_documentType
-description
我想选择表中没有文档的所有车辆。表中有4个特定id的文档

大概是这样的:

Car1 | TaxDocument
Car1 | KeyDocument
Car2 | TaxDocument

有了这些,我知道我丢失了两个car1文档和一个car2文档。

您可以使用下面的查询获得结果:

SELECT
    c.description,
    dt.description
FROM
    Table_Cars c
    JOIN Table_CarDocuments cd ON c.id_car = cd.id_car
    JOIN Table_DocumentTypes dt ON cd.id_documentType = dt.id_documentType
WHERE
    dt.id_documentType NOT IN (1, 2, 3, 4) --replace with your document type id

您可以使用以下查询获得结果:

SELECT
    c.description,
    dt.description
FROM
    Table_Cars c
    JOIN Table_CarDocuments cd ON c.id_car = cd.id_car
    JOIN Table_DocumentTypes dt ON cd.id_documentType = dt.id_documentType
WHERE
    dt.id_documentType NOT IN (1, 2, 3, 4) --replace with your document type id

这可能是一个复杂的查询。其思想是使用交叉连接生成所有汽车组合和所需的四个文档。然后使用left join确定文档是否实际存在:

select c.id_car, dd.doctype
from cars c cross join
     (select 'doc1' as doctype union all
      select 'doc2' union all
      select 'doc3' union all
      select 'doc4'
     ) dd left join
     CarDocuments cd
     on c.id_car = cd.id_car left join
     Documents d
     on cd.id_document_type = d.id_document_type and d.doctype = dd.doctype
where dd.id_document_type is null;

最后,where子句查找数据中不存在的car/doctype对。

这可能是一个复杂的查询。其思想是使用交叉连接生成所有汽车组合和所需的四个文档。然后使用left join确定文档是否实际存在:

select c.id_car, dd.doctype
from cars c cross join
     (select 'doc1' as doctype union all
      select 'doc2' union all
      select 'doc3' union all
      select 'doc4'
     ) dd left join
     CarDocuments cd
     on c.id_car = cd.id_car left join
     Documents d
     on cd.id_document_type = d.id_document_type and d.doctype = dd.doctype
where dd.id_document_type is null;

最后,where子句查找数据中不存在的car/doctype对。

您正在查找丢失的car文档。因此,交叉连接cars和文档类型,并查找不在car douments表中的组合

select c.description as car, dt.description as doctype
from table_cars c
cross join table_documenttypes dt
where (c.id_car, dt.id_documenttype) not in
(
  select cd.id_car, cd.id_documenttype
  from table_cardocuments cd
);
更新:这表明SQLServer的IN子句非常有限,无法处理值列表。但NOT IN条款很容易被NOT EXISTS替换:

select c.description as car, dt.description as doctype
from table_cars c
cross join table_documenttypes dt
where not exists
(
  select *
  from table_cardocuments cd
  where cd.id_car = c.id_car
  and cd.id_documenttype = dt.id_documenttype
);
更新:由于您只对必须在查询中添加的特定id_documenttype和1、2、3、4中的dt.id_documenttype感兴趣,因此可以动态为它们生成记录,而无需读取表_documenttype

为了做到这一点,请更换

cross join table_documenttypes dt


你正在寻找丢失的汽车文件。因此,交叉连接cars和文档类型,并查找不在car douments表中的组合

select c.description as car, dt.description as doctype
from table_cars c
cross join table_documenttypes dt
where (c.id_car, dt.id_documenttype) not in
(
  select cd.id_car, cd.id_documenttype
  from table_cardocuments cd
);
更新:这表明SQLServer的IN子句非常有限,无法处理值列表。但NOT IN条款很容易被NOT EXISTS替换:

select c.description as car, dt.description as doctype
from table_cars c
cross join table_documenttypes dt
where not exists
(
  select *
  from table_cardocuments cd
  where cd.id_car = c.id_car
  and cd.id_documenttype = dt.id_documenttype
);
更新:由于您只对必须在查询中添加的特定id_documenttype和1、2、3、4中的dt.id_documenttype感兴趣,因此可以动态为它们生成记录,而无需读取表_documenttype

为了做到这一点,请更换

cross join table_documenttypes dt


感谢@Thorsten Kettner的帮助

select c.description as car, dt.description as doctype
from table_cars c
cross join table_documenttypes dt
where dt.id no in (
(
  select cd.id_documentType
  from table_cardocuments cd
  where cd.idcar = c.id AND cd.id_doctype = dt.id
)
AND dt.id IN (1, 2, 3, 4)

感谢@Thorsten Kettner的帮助

select c.description as car, dt.description as doctype
from table_cars c
cross join table_documenttypes dt
where dt.id no in (
(
  select cd.id_documentType
  from table_cardocuments cd
  where cd.idcar = c.id AND cd.id_doctype = dt.id
)
AND dt.id IN (1, 2, 3, 4)

样本数据和期望的结果有帮助。你想让四份文件全部丢失吗?或者,如果四个文件中有任何一个丢失了,您是否希望为每个carSample数据和所需结果的每个丢失的文档获取一行帮助。你想让四份文件全部丢失吗?或者,如果四个文件中有一个丢失了,你想为每辆车的每个文件丢失一行吗?如果一辆车已经有了其中一个文件,它没有其他三个文件,它不会出现在results@DiogoAlmeida . . . 这很奇怪。这应该是可行的。当一辆车已经有了其中一个文档而没有其他3个文档时,它不会显示在results@DiogoAlmeida . . . 这很奇怪。这应该可以工作。在MS SQL中不工作。它是这样的:从表中选择c.description作为car,从表中选择dt.description作为doctype,从表中选择dt.id作为doctype,从表中选择dt.id作为doctype,从表中选择cd.id作为doctype,从表中选择cd.id作为doctype,其中cd.idcar=c.id和cd.id\u doctype=dt.id和dt.id在1、2、3、4中不起作用意味着什么?错误?唱片太多了?太少了?至于语法:IN后面有一个括号太多了。您在中写了NO而不是NOT IN。并且您的IN子句被混淆了。IN子句应该是非相关的,但您在子查询中引用了dt值。你为什么要改变它?SQL Server是否无法处理元组?大概那就让这个不存在。我会马上编辑我的答案。我刚刚查过了;列列表[不]在。。。在SQL Server中似乎不支持,我认为这是一个遗憾,因为我认为这个特性使得查询非常可读。因此,在SQL Server中处理多个值时,必须使用[NOT]EXISTS。以下是关于IN子句的文档:。我认为MS SQL无法处理以下问题:“where c.id_car,dt.id_documenttype”在MS SQL中不起作用。它是这样的:从表中选择c.description作为car,从表中选择dt.description作为doctype,从表中选择dt.id作为doctype,从表中选择dt.id作为doctype,从表中选择cd.id作为doctype,从表中选择cd.id作为doctype,其中cd.idcar=c.id和cd.id\u doctype=dt.id和dt.id在1、2、3、4中不起作用意味着什么?错误?唱片太多了?太少了?至于语法:IN后面有一个括号太多了。您在中写了NO而不是NOT IN。并且您的IN子句被混淆了。IN子句应该是非相关的,但您在子查询中引用了dt值。你为什么要改变它?SQL Server是否无法处理元组?大概那就让这个不存在。我会马上编辑我的答案。我刚刚查过了;列列表[不]在。。。似乎不支持SQL Server,我认为这是一个遗憾,因为我认为THI
的特性使查询非常可读。因此,在SQL Server中处理多个值时,必须使用[NOT]EXISTS。以下是关于IN子句的文档:。我认为MS SQL无法处理以下问题:“where c.id\u car,dt.id\u documenttype”