Database 如何有效地连接3个表M:N

Database 如何有效地连接3个表M:N,database,postgresql,Database,Postgresql,我有几张桌子: 应用程序: id | name | url_key =================== 1 | Hello World | hello-world 2 | Snake 2 | snake-2 id | name | url_key =================== 1 | Mr. Robinson | mr-robinson 2 | Richard | richard 3 | Nokia | nokia 开发者: id | name | url_key =

我有几张桌子:

应用程序

id | name | url_key
===================
1  | Hello World | hello-world
2  | Snake 2 | snake-2
id | name | url_key
===================
1  | Mr. Robinson | mr-robinson
2  | Richard | richard
3  | Nokia | nokia
开发者

id | name | url_key
===================
1  | Hello World | hello-world
2  | Snake 2 | snake-2
id | name | url_key
===================
1  | Mr. Robinson | mr-robinson
2  | Richard | richard
3  | Nokia | nokia
应用程序开发人员分配

app_id | developer_id
=====================
1      | 1
1      | 2
2      | 3
因此,正如您所看到的,一个应用程序可能有多个开发人员

我实际需要的是编写一个PostgreSQL查询,以选择所有包含相关开发人员有用信息的应用程序。 e、 像这样的东西:

Hello World | 1-hello-world | Mr.Robinson<1-mr-robinson> /and 1 more/
Snake 2     | 2-snake-2     | Nokia<3-nokia>
SELECT * FROM apps a
LEFT JOIN apps_developers_assignment ada ON a.id = ada.app_id
                                            AND ada.developerid = :devid

LEFT JOIN developers d ON ada.developer_id = d.id

WHERE a.id = :appid
Hello World | 1-Hello-World | Robinson先生/还有1个/
Snake 2 | 2-Snake-2 |诺基亚
因此,如果应用程序有一个开发人员,只需将开发人员的姓名、url键和id附加到应用程序,如果应用程序有更多的开发人员,则附加第一个并附加“有多少开发人员”的信息

最重要的是-我需要最终过滤结果(例如,不返回指定开发人员的应用程序)

我知道这可以通过为应用程序本身编写第一个查询,然后每行发送下一个查询来解决,但我认为这不是一个好办法

如果我只是简单地加入表:

SELECT * FROM apps a
LEFT JOIN apps_developers_assignment ada ON a.id = ada.app_id
LEFT JOIN developers d ON ada.developer_id = d.id

Hello World | 1-hello-world | Mr.Robinson<1-mr-robinson>
Hello World | 1-hello-world | Richard<2-richard>
Snake 2     | 2-snake-2     | Nokia<3-nokia>
从应用程序a中选择*
左加入apps\u开发者\u分配ada ON a.id=ada.app\u id
在ada.developer\u id=d.id上左键连接开发人员d
你好,世界1-你好,世界罗宾逊先生
你好世界| 1-你好世界|理查德
Snake 2 | 2-Snake-2 |诺基亚

它返回重复的应用程序。。。我不知道如何按开发人员筛选这些结果(如我上面所写)。

如果您想使用左联接,您需要将您的条件放在联接上,否则它将装箱一个内部联接,并且不会返回包含null的行。。。试着这样做:

Hello World | 1-hello-world | Mr.Robinson<1-mr-robinson> /and 1 more/
Snake 2     | 2-snake-2     | Nokia<3-nokia>
SELECT * FROM apps a
LEFT JOIN apps_developers_assignment ada ON a.id = ada.app_id
                                            AND ada.developerid = :devid

LEFT JOIN developers d ON ada.developer_id = d.id

WHERE a.id = :appid

如果要使用左联接,需要将条件放在联接上,否则它将装入一个内部联接,并且将不会返回中为null的行。。。试着这样做:

Hello World | 1-hello-world | Mr.Robinson<1-mr-robinson> /and 1 more/
Snake 2     | 2-snake-2     | Nokia<3-nokia>
SELECT * FROM apps a
LEFT JOIN apps_developers_assignment ada ON a.id = ada.app_id
                                            AND ada.developerid = :devid

LEFT JOIN developers d ON ada.developer_id = d.id

WHERE a.id = :appid

假设您只想筛选出一个开发人员,则需要传递一个参数。为此,我将此参数/变量称为@excludeDevId

我对T-SQL更为熟悉,因此这可能/也将需要Postgres中的等效语法。此外,由于左连接,我将null保留为null——从您的输出中,您可能希望合并(可能还有其他一些输出调整)。这是即兴的、未经测试的,但至少应该足以让你朝着正确的方向前进:

SELECT 
    a.name AppName, 
    a.id AppId,
    d.id DevId,
    d.url_key Url,
    d.name DevName,
    CAST(agg.dev_count - 1 as VARCHAR) + ' more'
FROM 
    (
    SELECT 
        MAX(ada.developer_id) first_dev_id, 
        COUNT(ada.developer_id) dev_count, 
        app_id
    FROM
        apps_developers_assignment ada 
    WHERE 
        d.id != @excludeDevId
    GROUP BY
        app_id
    ) agg
    INNER JOIN apps a ON a.id = agg.app_id
    LEFT JOIN developers d ON agg.developer_id = d.id

假设您只想筛选出一个开发人员,则需要传递一个参数。为此,我将此参数/变量称为@excludeDevId

我对T-SQL更为熟悉,因此这可能/也将需要Postgres中的等效语法。此外,由于左连接,我将null保留为null——从您的输出中,您可能希望合并(可能还有其他一些输出调整)。这是即兴的、未经测试的,但至少应该足以让你朝着正确的方向前进:

SELECT 
    a.name AppName, 
    a.id AppId,
    d.id DevId,
    d.url_key Url,
    d.name DevName,
    CAST(agg.dev_count - 1 as VARCHAR) + ' more'
FROM 
    (
    SELECT 
        MAX(ada.developer_id) first_dev_id, 
        COUNT(ada.developer_id) dev_count, 
        app_id
    FROM
        apps_developers_assignment ada 
    WHERE 
        d.id != @excludeDevId
    GROUP BY
        app_id
    ) agg
    INNER JOIN apps a ON a.id = agg.app_id
    LEFT JOIN developers d ON agg.developer_id = d.id

你被困在哪里?你有什么问题吗?@Oded我已经修改了这个问题,我希望现在更清楚了,你被困在哪里了?你有什么问题?@Oded我已经修改了这个问题,我希望现在问题更清楚了,如果你不想返回空值,请将联接设置为“内部联接”,并将条件放在WHERE子句中。如果你不想返回空值,请将联接设置为“内部联接”,并将条件放在WHERE子句中。