I have these tables:
CREATE TABLE poster (
    poster_id SERIAL NOT NULL  PRIMARY KEY,
    country VARCHAR ( 50 ) NOT NULL
);
CREATE TABLE batch (
    batch_id SERIAL NOT NULL PRIMARY KEY,
    price VARCHAR ( 50 ) NOT NULL
);
ALTER TABLE poster 
    ADD COLUMN batch_id SERIAL REFERENCES batch (batch_id);
INSERT INTO batch (price) VALUES (10)
INSERT INTO batch (price) VALUES (11)
INSERT INTO poster (country, batch_id) VALUES ('DEU', 1);
INSERT INTO poster (country, batch_id) VALUES ('DEU', 1);
INSERT INTO poster (country, batch_id) VALUES ('FRA', 1);
I want get how many posters I have for a particular country, for the rest of the world and the total, grouped by batch.
This code solves the problem, but I want to know if there's a more performant query.
SELECT 
    batch.batch_id, 
    germany.count AS germany, 
    other.count AS outside, 
    total.count AS total 
FROM
    batch 
LEFT JOIN
    (SELECT 
         poster.batch_id AS batch_id, 
         COUNT(*) AS count 
     FROM
         poster 
     WHERE
         poster.country = 'DEU' 
     GROUP BY
         poster.batch_id) AS germany ON germany.batch_id = batch.batch_id
LEFT JOIN
    (SELECT
         poster.batch_id AS batch_id, 
         COUNT(*) AS count 
     FROM
         poster 
     WHERE
         poster.country <> 'DEU' 
     GROUP BY
         poster.batch_id) AS other ON other.batch_id = batch.batch_id
LEFT JOIN
    (SELECT
         poster.batch_id AS batch_id, 
         COUNT(*) AS count 
     FROM
         poster 
     GROUP BY
         poster.batch_id) AS total ON total.batch_id = batch.batch_id
Also when the batch doesn't have any poster I want to return 0 instead of null.
 
                        
In modern (>=9.4) PostgreSQL (that you tagged the question with), you can use a
filterclause on an aggregate function and use that to apply conditions on the rows effected by the function. With this technique, you can reduce the query to a singleleft join:SQLFiddle demo
If you don't want to use PostgreSQL-specific syntax, you could use
caseexpressions instead:SQLFiddle demo