2011-04-17 5 views
1

У меня есть несколько таблиц:Как эффективно объединить 3 таблицы M: N

приложение:

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-Присваивающих

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

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

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

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> 

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

+0

Куда вы застряли? С чем вы сталкиваетесь? – Oded

+0

@Oded я изменил вопрос, надеюсь, теперь будет более ясно –

ответ

1

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

Я более знаком с T-SQL, поэтому для Postgres это может также понадобиться эквивалентный синтаксис. Кроме того, я оставляю nulls в результате левого соединения как null - из вашего вывода вы, вероятно, хотите 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

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

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 
+0

, если вы не хотите возвращать возвращаемые значения null, сделайте свои объединения «внутренними соединениями» и поместите свои условия в предложение WHERE. –

Смежные вопросы