Get count of foreign key from multiple tables

前端 未结 3 967
滥情空心
滥情空心 2021-01-18 17:39

I have 3 tables, with Table B & C referencing Table A via Foreign Key. I want to write a query in PostgreSQL to get all ids from A and also their total occurrences from

相关标签:
3条回答
  • 2021-01-18 18:16

    Another option:

    SELECT
        a.id,
        (SELECT COUNT(*) FROM b WHERE b.a_id = a.id) +
        (SELECT COUNT(*) FROM c WHERE c.a_id = a.id)
    FROM
        a
    
    0 讨论(0)
  • 2021-01-18 18:19

    Use left join with a subquery:

    SELECT a.id, COUNT(x.id)
    FROM a
    LEFT JOIN (
        SELECT id, a_id FROM b
        UNION ALL
        SELECT id, a_id FROM c
    ) x ON (a.id = x.a_id)
    GROUP BY a.id;
    
    0 讨论(0)
  • 2021-01-18 18:22

    If the query involves large parts of b and / or c it is more efficient to aggregate first and join later.
    I expect these two variants to be considerably faster:

    SELECT a.id,
          ,COALESCE(b.ct, 0) + COALESCE(c.ct, 0) AS bc_ct
    FROM   a
    LEFT   JOIN (SELECT a_id, count(*) AS ct FROM b GROUP BY 1) b USING (a_id)
    LEFT   JOIN (SELECT a_id, count(*) AS ct FROM c GROUP BY 1) c USING (a_id);
    

    You need to account for the possibility that some a_id are not present at all in a and / or b. count() never returns NULL, but that's cold comfort in the face of LEFT JOIN, which leaves you with NULL values for missing rows nonetheless. You must prepare for NULL. Use COALESCE().

    Or UNION ALL a_id from both tables, aggregate, then JOIN:

    SELECT a.id
          ,COALESCE(ct.bc_ct, 0) AS bc_ct
    FROM   a
    LEFT   JOIN (
       SELECT a_id, count(*) AS bc_ct
       FROM (
          SELECT a_id FROM b
          UNION ALL
          SELECT a_id FROM c
          ) bc
       GROUP  BY 1
       ) ct USING (a_id);
    

    Probably slower. But still faster than solutions presented so far. And you could do without COALESCE() and still not loose any rows. You might get occasional NULL values for bc_ct, in this case.

    0 讨论(0)
提交回复
热议问题