【问题标题】:PostgreSQL - Join three tables and add conditions?PostgreSQL - 加入三个表并添加条件?
【发布时间】:2019-09-03 18:05:01
【问题描述】:

我在 PostgreSQL 数据库中有三个表,如下所示:https://imgur.com/a/bUapsYi

一个用户可以属于多个项目,一个项目可以有多个用户,我通过一个名为“userprojects”的连接表将它们联系在一起。

每个表可能如下所示:

User

| id | firstname | lastname | email          |
|----|-----------|----------|----------------|
| 1  | Joe       | Green    | joe@green.com  |
| 2  | Olle      | Svensson | olle@gmail.com |
| 3  | Erik      | Yapp     | erik@yapp.com  |

Project

| id | name          | owner          |
|----|---------------|----------------|
| 1  | Project X     | joe@green.com  |
| 2  | Peanut Butter | olle@gmail.com |
| 3  | Apollo 11     | erik@yapp.com  |
| 4  | RCPP          | erik@yapp.com  |

Userprojects

| id | user_id | project_id |
|----|---------|------------|
| 1  | 1       | 1          |
| 2  | 1       | 2          |
| 3  | 2       | 3          |
| 4  | 3       | 3          |

是否有某种形式的内部(?)连接让我查询项目中的用户(例如,userprojects 中的 user_id)或者用户是否是项目的所有者?

在上面的示例中,内连接查询如下所示:

SELECT "project".id, "project".name, "email" 
FROM userprojects 
INNER JOIN project ON userprojects.project_id = project.id 
INNER JOIN "user" ON userprojects.user_id = "user".id

会返回这个:

| id | name          | email          |
|----|---------------|----------------|
| 1  | Project X     | joe@green.com  |
| 2  | Peanut Butter | joe@green.com  |
| 3  | Apollo 11     | olle@gmail.com |
| 4  | Apollo 11     | erik@yapp.com  |

如果在该内部联接查询中找不到每个项目的所有者,我希望添加到查询结果中的内容也是 - 请注意 erik@yapp.com 是项目 RCPP 的所有者,但由于未找到该关系在userprojects 表中,它不会在查询中返回。我能否以某种方式让我的查询返回这些用户,例如:

| id  | name          | email          |
|-----|---------------|----------------|
| 1   | Project X     | joe@green.com  |
| 2   | Peanut Butter | joe@green.com  |
| 3   | Apollo 11     | olle@gmail.com |
| 4   | Apollo 11     | erik@yapp.com  |
| (?) | RCPP          | erik@yapp.com  |

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    Project 表开始连接并将它们转换为LEFT 连接:

    SELECT 
     "project".id, "project".name, 
     COALESCE("User"."email", "project"."owner") "owner" 
    FROM project
    LEFT JOIN userprojects  ON userprojects.project_id = project.id 
    LEFT JOIN "User" ON userprojects.user_id = "User".id
    

    请参阅demo
    结果:

    | id  | name          | owner          |
    | --- | ------------- | -------------- |
    | 1   | Project X     | joe@green.com  |
    | 2   | Peanut Butter | joe@green.com  |
    | 3   | Apollo 11     | olle@gmail.com |
    | 3   | Apollo 11     | erik@yapp.com  |
    | 4   | RCPP          | erik@yapp.com  |
    

    【讨论】:

    • Hmm.. 这会改变查询的结构 - 如果将 user_id 添加到 userprojects 中的项目中(即使该用户不是所有者),查询将显示已添加用户作为所有者
    • 您的代码在结果中包含“电子邮件”,我保留了它。这是你想要的吗?还是只是 project.owner?
    • 因此,如果您尝试将用户 3 添加到 userprojects 表中的项目 2 - 我希望它也出现在查询中 - 即使 erik@yapp.com 不是项目Peanut Butter
    • 哦,你是对的,它确实如此,但我无法让它在我的本地 postgres 数据库中工作 - 它是否必须做一些不显示唯一值的事情? db-fiddle 看起来是正确的,但是当我在终端中执行此操作时,我只会看到唯一的 ID,因为我将 project 表中的 id 设置为唯一
    【解决方案2】:

    您可以使用user 表创建第二个INNER JOIN,但是这个

    user 表的email 列与project 表的owner 匹配的时间。

    SELECT p.id, P.name, email, CONCAT(u2.firstname, " ", u.lastname) as owner
    FROM userprojects up
    INNER JOIN project p ON(up.project_id = p.id)
    INNER JOIN user u ON(up.user_id = u.id)
    INNER JOIN user u2 ON(u2.email = p.owner)
    

    【讨论】:

    • 问题是,我希望将所有用户添加到结果中 - 如果他们是项目的所有者或者他们的 user_id 存在于 userprojects 表中
    • @erikvm 所以如果用户是一个项目的所有者并且他们是另一个项目的成员,他们的名字会出现两次?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    • 2015-11-22
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    相关资源
    最近更新 更多