连接三个表以获得特定结果

Posted

技术标签:

【中文标题】连接三个表以获得特定结果【英文标题】:join three tables for specific result 【发布时间】:2018-11-05 13:39:02 【问题描述】:

我有三张桌子:

表 1 Users:

+----------+------------+------------+-------------------+
| ID [PK]  |  username  |  password  |  user_struct [FK] |
+----------+------------+------------+-------------------+
|       1  |  SAM       |       123  |  CIF              |
|       2  |  JACK      |       123  |  ADM              |
|       3  |  JAMAL     |       123  |  SDT              |
+----------+------------+------------+-------------------+

表 2 CR_AR:

+-------------+-------+--------------+
| ID_CR [PK]  |  NUM  |  STRUCT [FK] |
+-------------+-------+--------------+
|          1  |   11  |  CIF         |
|          2  |   22  |  ADM         |
|          3  |   33  |  SDT         |
+-------------+-------+--------------+

表 3 STRUCT:

+-----------------+--------------+
| STRUCTURE [PK]  |  description |
+-----------------+--------------+
| CIF             |  NULL        |
| IDM             |  NULL        |
| SDT             |  NULL        |
+-----------------+--------------+

我需要连接三个表,以便只有当三个表中的STRUCT 值相同时,我才能从CR_AR 表中获取数据。

这是我编写的 SQL 查询,但它似乎返回所有数据,即使 USERS 中的 user_struct 不等于 CR_AR 中的 STRUCT

SELECT * FROM CR_AR AS C 
    LEFT JOIN STRUCT AS S ON S.STRUCTURE = C.STRUCT 
    LEFT JOIN USERS AS U ON U.USER_STRUCT = S.STRUCTURE

【问题讨论】:

把所有的“Left join”改成“Join” 你为什么使用左连接?你看过第一次左连接后的结果吗? (绝对是基本的调试。)你明白左连接返回内连接行加上空值扩展的不匹配左表行吗? 【参考方案1】:

LEFT JOIN 将始终返回连接 左侧 表中的 所有 记录,并且仅返回与连接表中的连接条件匹配的记录中的值连接的右侧

要仅返回为每条记录验证了连接条件的记录,您应该使用INNER JOIN,即:

SELECT * 
FROM 
    CR_AR C 
    INNER JOIN STRUCT S ON S.STRUCTURE = C.STRUCT 
    INNER JOIN USERS U ON U.USER_STRUCT = S.STRUCTURE

【讨论】:

对!但即使 CR_AR 中的 STRUCT 不等于 USER 中的 STRUCT,查询仍会返回所有数据 SAM 的示例我希望它只返回 1 | 11 不是CR_AR的全部数据 @YOUCEFsami 请提供完整的示例数据并显示您在运行查询时获得的结果。 @YOUCEFsami Lee 的查询将只返回来自 CR_AR 的 Users.username='SAM' 的 1/11 行。在您提出问题之前,您是否尝试过运行它?【参考方案2】:

您的数据示例谈到了外键,但表 STRUCT 不包含 ADM,而是 IDM。所以那里有些不一致。

如果您不想返回所有行,则不应使用外连接。请改用内部连接。

根据您的示例,这是我的测试,其中包含一些您可能会发现有用的建议查询:

create table users (
    id int,
    username varchar(10),
    pwd varchar(10),
    user_struct varchar(3)
)

create table cr_ar (
    id int,
    num int,
    struct varchar(3)
)

create table struct (
    structure varchar(3),
    description varchar(10)
)

insert into users values (1, 'sam', 123, 'CIF')
insert into users values (2, 'jack', 123, 'ADM')
insert into users values (3, 'jamal', 123, 'SDT')

insert into cr_ar values (1, 11, 'CIF')
insert into cr_ar values (2, 22, 'ADM')
insert into cr_ar values (3, 33, 'SDT')

insert into struct values ('CIF', null)
insert into struct values ('IDM', null)
insert into struct values ('SDT', null)

-- your query
SELECT * FROM CR_AR AS C 
LEFT JOIN STRUCT AS S ON S.STRUCTURE = C.STRUCT 
LEFT JOIN USERS AS U ON U.USER_STRUCT = S.STRUCTURE

-- no outer joins
SELECT * FROM CR_AR AS C 
JOIN STRUCT AS S ON S.STRUCTURE = C.STRUCT 
JOIN USERS AS U ON U.USER_STRUCT = S.STRUCTURE

-- alternative with outer joins (showing struct ADM does not exist)
SELECT * FROM CR_AR AS C 
LEFT JOIN USERS AS U ON U.USER_STRUCT = C.struct
LEFT JOIN struct AS s ON s.structure = c.struct

【讨论】:

对不起,是ADM,写错了,表STRUCT包含ADM 那我不明白你说“USERS 中的 user_struct 不等于 CR_AR 中的 STRUCT”。在您的示例中,两个表在其“结构”列中包含相同的值集。

以上是关于连接三个表以获得特定结果的主要内容,如果未能解决你的问题,请参考以下文章

如何连接三个表以获得总和

如何在 SQL Server 中填充我的日期维度表以获得具有此特定值的列?

连接表以连接每个可能的组合

使用两个不同的外键连接两个表以获得相同的字段

如何连接表以选择连接表中的最大行? [复制]

基于 mysql 视图结果创建表以加快获取速度