Как эффективно объединить 3 стола M: N - PullRequest
1 голос
/ 17 апреля 2011

У меня есть несколько таблиц:

Apps

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

Программы-Developers-Assignment

app_id | developer_id
=====================
1      | 1
1      | 2
2      | 3

Как видите, у одного приложения может быть несколько разработчиков.

Что мне действительно нужно, так это написать запрос PostgreSQL, чтобы выбрать все приложения с некоторой полезной информацией о связанных разработчиках. например вот так:

Hello World | 1-hello-world | Mr.Robinson<1-mr-robinson> /and 1 more/
Snake 2     | 2-snake-2     | Nokia<3-nokia>

Так что, если в приложении есть один разработчик, просто добавьте имя разработчика, URL-адрес и идентификатор к приложению, если в нем больше разработчиков, добавьте первое и добавьте информацию о том, «сколько там разработчиков».

И что самое важное - мне нужно со временем отфильтровать результаты (например, не возвращать приложения от какого-то указанного разработчика).

Я знаю, что это можно решить, написав первый запрос для самих приложений, а затем отправив следующий запрос для каждой строки, но я думаю, что это не очень хороший способ ...

Если я просто присоединюсь к столу:

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>

Возвращает дубликаты приложений ... и я не знаю, как отфильтровать эти результаты по разработчикам (как я писал выше).

Ответы [ 2 ]

1 голос
/ 17 апреля 2011

Если вы хотите отфильтровать только одного разработчика, вам нужно будет передать параметр. Для этого я вызываю этот параметр / переменную @excludeDevId.

Я гораздо более знаком с T-SQL, так что для этого может потребоваться эквивалентный синтаксис в Postgres. Кроме того, я оставляю нулевые значения в результате левого соединения как нулевые - из вашего вывода вы, вероятно, захотите COALESCE (возможно, также некоторые другие выходные настройки). Это без манжеты и не проверено, но должно быть достаточно, чтобы заставить вас двигаться в правильном направлении, по крайней мере:

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
0 голосов
/ 17 апреля 2011

Если вы хотите использовать левое соединение, вам нужно поместить ваше условие в соединение, иначе оно создаст внутреннее соединение, и строки, которые имеют нулевое значение, не будут возвращены ... попробуйте что-то вроде это:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...