sql连接两个以上的表

Posted

技术标签:

【中文标题】sql连接两个以上的表【英文标题】:Sql join more than two tables 【发布时间】:2021-12-26 14:22:39 【问题描述】:

我有三个表 transaction、transaction-docs 和 generic-transaction-task。 transaction-docs 和 generic-transaction-task 表是在参数transactionId(外键关系)上的transaction table 上关联的。我想将这三个表连接起来,并根据transactionid 获取数据。

我想根据transactionid从这三个表中获取数据。

如果我尝试使用以下查询,则获取重复记录。

select A.Id , B.Id , c.Id 
from  [velvet_elves].[dbo].[Transactions] as A
Left  join [dbo].[TransactionsDocs] as C On A.Id = C.TransactionId
Left  join [dbo].[GenericTransactionTask] as B on A.Id = B.TransactionId
Where A.Id in (24147, 24149) 

【问题讨论】:

好的,所以.. 到目前为止你写过任何东西吗?或者用谷歌搜索任何东西,发现任何你不明白的东西? 我已经更新了我的查询。请看一下 然后获取重复记录 - 唯一可能发生的方法是这些 Id 在表中重复。将其称为 Id 会假设它是 PK,但即使每个 tran 有 2 个文档,每个 tran 有 2 个任务,爆炸为 4,ID 也将是唯一的 能否请您给我查询一下? 我个人不能,因为我不知道你在期待什么。绘制或写出您希望输出的样子,然后我可以更好地解释为什么您当前获得的输出与您的期望不符 【参考方案1】:

如果我尝试使用以下查询,则获取重复记录。

这听起来像是查询正在做它应该做的事情,只是你要么不了解 JOIN 做什么,要么你不了解数据的关系。

发生的情况是,一个(或多个)连接表上有多个满足您给定条件的记录。然后发生的事情是每个匹配的记录都将被放置在结果中,并加入到每个匹配的记录中。所以如果有多个匹配的记录,你会得到相同的Id出现多次。

在不知道您的表格或数据的情况下,我无法更具体。

【讨论】:

例如:事务表中有一条记录。在事务文档表中,有两条记录,在事务任务表中,有五条记录。如果我运行该查询,那么我有 10 条记录,但我只需要 7 条记录【参考方案2】:

然后得到重复记录。

如果这些 Id 列是正确唯一的,您不应该这样做

如果你有:

Transactions
1, Tran1

TransactionDocs
Id, TransactionId, Name
1, 1, TranDoc1
2, 1, TranDoc2

GenericTranTasks
Id, TransactionId, Name
1, 1, GenericTranTask1
2, 1, GenericTranTask2

当您加入时,您将获得一切:

TransId, TranName, DocId, DocTranId, DocName, TaskId, TaskTranId, TaskName 
1, Tran1, 1, 1, TranDoc1, 1, 1, GenericTranTask1
1, Tran1, 2, 1, TranDoc2, 1, 1, GenericTranTask1
1, Tran1, 1, 1, TranDoc1, 2, 1, GenericTranTask2
1, Tran1, 2, 1, TranDoc2, 2, 1, GenericTranTask2
^         ^               ^

(您只选择下面带有^ 的那些列)

这些东西中的每一个都是独一无二的,但你不能只看一列中的数据就说“tran id 重复了 4 次!” - 您必须查看总记录,当您将所有 3 个数字一起考虑时,这些都是唯一的:

1, 1, 1
1, 2, 1
1, 1, 2
1, 2, 2

这本质上只是一棵数据树的平面渲染,如下所示:

    1
   /
  1--2
 / 
1
 \
  2--1
   \
    2

..当你要求它们加入数据时,这就是数据库所做的;它们输出一个矩形块,并在必要时重复各个输入记录

每次添加另一个连接时,都会长出树;您将更多的叶子添加到当前是叶子的所有内容中。根据您在 cmets 中所说的,您实际上需要的是两棵独立的树。

总而言之,您将根本不相关的数据连接在一起:一个 tran 任务和一个 tran doc 没有任何关系,就像一个人的工作历史和他们的亚马逊订单历史不相关 - 只是因为我这辈子做过 6 份工作,而且我这辈子从亚马逊订购了 20 件东西;并不意味着我应该带着我的订单加入我的工作(120 条记录结果)。现在,您可以建立关系,将问题重新定义为“您从事过哪些工作,在从事这些工作时,您从亚马逊订购了什么”——在这种情况下,我们坚持order.order_date 介于job.hire_datejob.fire_date 之间,这样就可以利用这种爆炸性关系,即每个工作都与每个订单交叉,并对其进行限制,以便工作和订单相关基于每次发生的日期 - 但您必须提出正确的问题 ..

我怀疑您可能没有针对您的数据提出正确的问题..

【讨论】:

例如:事务表中有一条记录。在事务文档表中,有两条记录,在事务任务表中,有五条记录。如果我运行该查询,那么我有 10 条记录,但我只需要 7 条记录 是的,你得到 10 条记录,因为 1 tran 乘以 2 docs 乘以 5 任务是 10 (1*2*5=10)。你可以用 SELECT tran.id, docs.id, 'doc' as x FROM tran JOIN docs ON .. UNION ALL SELECT tran.id, tasks.id, 'task' FROM tran JOIN tasks ON ... 得到 7 条记录 - 这将得到 7 条记录。但它更难使用。老实说,您最好只执行两个查询:SELECT * FROM docs where tranid = ...SELECT * FROM tasks where tranid = ... - 如果您愿意,您可以将 tran 加入其中;它不会影响记录数,因为 tran 在上下文中是唯一的

以上是关于sql连接两个以上的表的主要内容,如果未能解决你的问题,请参考以下文章

连接两个以上的表时,Oracle 连接消除无法按预期工作

当涉及两个以上的表时,如何将来自相似字段的单个表的两个左连接转换为 LINQ? [复制]

在 Spring Data JPA 中使用注释连接两个以上的表

SQL多表链接查询、嵌入SELECT语句的子查询技术

用于连接两个按连接逻辑排序的表的最佳 SQL 查询

如何使用 SQL 和 Python 连接两个具有日期条件的表?