How to find missing values across multiple OUTER JOINs - Mailing list pgsql-sql
From | Drew |
---|---|
Subject | How to find missing values across multiple OUTER JOINs |
Date | |
Msg-id | 4FD9368D-D4CA-44CF-887B-EBB64DCE46BA@fastmail.fm Whole thread Raw |
Responses |
Re: How to find missing values across multiple OUTER JOINs
Re: How to find missing values across multiple OUTER JOINs |
List | pgsql-sql |
I'm having troubles using multiple OUTER JOINs, which I think I want to use to solve my problem. My problem is to find all non-translated string values in our translations database, given the 4 following tables: SOURCE (source_id PRIMARY KEY, language_id, value, ...) TRANSLATION (translation_id PRIMARY KEY, language_id, value, ...) TRANSLATION_PAIR (source_id, translation_id) LANGUAGE(language_id PRIMARY KEY, name) This seems to me the appropriate situation for using OUTER JOINs, but I cannot figure out how to get the null rows without the not-null rows. Here's my best guess at this query: SELECT s.source_id,tp.translation_pair_id,t.translation_id,t.language_id, l.name FROM source s LEFT OUTER JOIN translation_pair tp USING(source_id) LEFT OUTER JOIN translation t ON tp.translation_id = t.translation_id AND t.translation_id is null) RIGHT OUTER JOIN language l on l.language_id = t.language_id; To test this query, I have a string that only has a translation in English and used it in this test query. SELECT s.source_id,tp.translation_pair_id,t.translation_id,t.language_id, l.name FROM (select * FROM source s WHERE source_id = 159986) as s LEFT OUTER JOIN translation_pair tp USING(source_id) LEFT OUTER JOIN translation t ON tp.translation_id = t.translation_id RIGHT OUTER JOIN language l on l.language_id = t.language_id; This yields promising results: source_id | translation_pair_id | translation_id | language_id | name -----------+---------------------+----------------+------------- +---------------------- | | | | Russian | | | | Danish | | | | Dutch 159986 | 1893187 | 1743833| 4 | English | | | | Finnish | | | | French | | | | German | | | | Italian | | | | Japanese | | | | Korean | | | | Norwegian | | | | Simplified Chinese | | | | Spanish | | | | Swedish | | | | Traditional Chinese | | | | Portuguese | | | | Polish | | | | Turkish | | | | Czech | | | | Brazilian Portuguese (20 rows) However, when I try to exclude the one not-null row, doing this: SELECT s.source_id,tp.translation_pair_id,t.translation_id,t.language_id, l.name FROM (select * FROM source s WHERE source_id = 159986) AS s LEFT OUTER JOIN translation_pair tp USING(source_id) LEFT OUTER JOIN translation t ON tp.translation_id = t.translation_id AND t.translation_id IS NULL RIGHT OUTER JOIN language l on l.language_id = t.language_id; I expect 19 rows, but instead get 20 rows, all containing null values. source_id | translation_pair_id | translation_id | language_id | name -----------+---------------------+----------------+------------- +---------------------- | | | | Russian | | | | Danish | | | | Dutch | | | | English | | | | Finnish | | | | French | | | | German | | | | Italian | | | | Japanese | | | | Korean | | | | Norwegian | | | | Simplified Chinese | | | | Spanish | | | | Swedish | | | | Traditional Chinese | | | | Portuguese | | | | Polish | | | | Turkish | | | | Czech | | | | Brazilian Portuguese (20 rows) I'm guessing I need to group the joins together, to avoid some associative problem. Do you see what I'm doing wrong? Thanks for the help, Drew