Reputation: 16126
I have few tables:
Apps:
id | name | url_key
===================
1 | Hello World | hello-world
2 | Snake 2 | snake-2
Developers:
id | name | url_key
===================
1 | Mr. Robinson | mr-robinson
2 | Richard | richard
3 | Nokia | nokia
Apps-Developers-Assignment
app_id | developer_id
=====================
1 | 1
1 | 2
2 | 3
So as you may see, one app may have more than one developer.
What i actually need is to write a PostgreSQL query to select all apps with some usefull information about related developers. e.g. sth like this:
Hello World | 1-hello-world | Mr.Robinson<1-mr-robinson> /and 1 more/
Snake 2 | 2-snake-2 | Nokia<3-nokia>
So if the app has one developer, just append the developer's name, url key and id to the app, if it has more developers, append the first and append the information of "how many developers are there".
And what's most important - i need to eventually filter the results (e.g. not return apps from some specified developer).
I know it can be solved by write first query for apps itself and then send next query per each row, but not the nice way, i think...
If i just simply JOIN the table:
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>
It returns duplicate apps... and i don't know how to filter these results by developer (as i wrote above).
Upvotes: 1
Views: 2097
Reputation: 28036
Assuming you only want to filter out one developer, you will need to pass a parameter. I am calling this parameter/variable @excludeDevId for this purpose.
I am much more familiar to T-SQL, so this may/will also need the equivalent syntax in Postgres. Also, I am leaving nulls as a result of the left join as null--from your output you probably want to COALESCE (probably some other output tweaks as well). This is off the cuff and untested, but should be enough to get you moving in the right direction at least:
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
Upvotes: 1
Reputation: 15409
If you want to use a left join, you'll need to put your condition on the join, otherwise it'll crate an inner join and the rows that have null in won't get returned... try something like this:
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
Upvotes: 0