Count for all values of enum in PostgreSQL












0














I have a table called users, which has the following columns:



id: INT NOT NULL
face: face_type


face_type is an ENUM type that has the following values: 'square', 'round' and 'triangle'.



And I have another table called houses, which has the following columns:



id: INT NOT NULL
user_id: INT NOT NULL


Now, I want to get all the houses grouped by the different type of face types. So, what I have so far is this:



SELECT users.face_type, COUNT(*)
FROM users
LEFT JOIN houses ON houses.user_id = users.id
GROUP BY users.face_type


The problem is that I also want to get rows for face_type which none of the users have, as well as a result for NULL face_type. So, for example, if I have the following data:



users (id, face_type)

1, 'round'
2, 'triangle'

houses (id, user_id)
1, 1
2, 1
3, 2


I would expect the result to be:



face_type, count
'round' 2
'triangle' 1
'square' 0
null 0


I know how to get all the potential values of the face_type ENUM, by doing :



SELECT unnest(enum_range(NULL::face_type)) AS face_types;


But I don't know how to use that to count all potential face types in the aggregate, as well as also calculating for NULL face types.










share|improve this question





























    0














    I have a table called users, which has the following columns:



    id: INT NOT NULL
    face: face_type


    face_type is an ENUM type that has the following values: 'square', 'round' and 'triangle'.



    And I have another table called houses, which has the following columns:



    id: INT NOT NULL
    user_id: INT NOT NULL


    Now, I want to get all the houses grouped by the different type of face types. So, what I have so far is this:



    SELECT users.face_type, COUNT(*)
    FROM users
    LEFT JOIN houses ON houses.user_id = users.id
    GROUP BY users.face_type


    The problem is that I also want to get rows for face_type which none of the users have, as well as a result for NULL face_type. So, for example, if I have the following data:



    users (id, face_type)

    1, 'round'
    2, 'triangle'

    houses (id, user_id)
    1, 1
    2, 1
    3, 2


    I would expect the result to be:



    face_type, count
    'round' 2
    'triangle' 1
    'square' 0
    null 0


    I know how to get all the potential values of the face_type ENUM, by doing :



    SELECT unnest(enum_range(NULL::face_type)) AS face_types;


    But I don't know how to use that to count all potential face types in the aggregate, as well as also calculating for NULL face types.










    share|improve this question



























      0












      0








      0







      I have a table called users, which has the following columns:



      id: INT NOT NULL
      face: face_type


      face_type is an ENUM type that has the following values: 'square', 'round' and 'triangle'.



      And I have another table called houses, which has the following columns:



      id: INT NOT NULL
      user_id: INT NOT NULL


      Now, I want to get all the houses grouped by the different type of face types. So, what I have so far is this:



      SELECT users.face_type, COUNT(*)
      FROM users
      LEFT JOIN houses ON houses.user_id = users.id
      GROUP BY users.face_type


      The problem is that I also want to get rows for face_type which none of the users have, as well as a result for NULL face_type. So, for example, if I have the following data:



      users (id, face_type)

      1, 'round'
      2, 'triangle'

      houses (id, user_id)
      1, 1
      2, 1
      3, 2


      I would expect the result to be:



      face_type, count
      'round' 2
      'triangle' 1
      'square' 0
      null 0


      I know how to get all the potential values of the face_type ENUM, by doing :



      SELECT unnest(enum_range(NULL::face_type)) AS face_types;


      But I don't know how to use that to count all potential face types in the aggregate, as well as also calculating for NULL face types.










      share|improve this question















      I have a table called users, which has the following columns:



      id: INT NOT NULL
      face: face_type


      face_type is an ENUM type that has the following values: 'square', 'round' and 'triangle'.



      And I have another table called houses, which has the following columns:



      id: INT NOT NULL
      user_id: INT NOT NULL


      Now, I want to get all the houses grouped by the different type of face types. So, what I have so far is this:



      SELECT users.face_type, COUNT(*)
      FROM users
      LEFT JOIN houses ON houses.user_id = users.id
      GROUP BY users.face_type


      The problem is that I also want to get rows for face_type which none of the users have, as well as a result for NULL face_type. So, for example, if I have the following data:



      users (id, face_type)

      1, 'round'
      2, 'triangle'

      houses (id, user_id)
      1, 1
      2, 1
      3, 2


      I would expect the result to be:



      face_type, count
      'round' 2
      'triangle' 1
      'square' 0
      null 0


      I know how to get all the potential values of the face_type ENUM, by doing :



      SELECT unnest(enum_range(NULL::face_type)) AS face_types;


      But I don't know how to use that to count all potential face types in the aggregate, as well as also calculating for NULL face types.







      sql postgresql enums group-by count






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 2 days ago









      GMB

      3,814519




      3,814519










      asked 2 days ago









      Hommer Smith

      8,76638112206




      8,76638112206
























          3 Answers
          3






          active

          oldest

          votes


















          0














          You can use LEFT JOIN:



          SELECT ft.face_type, COUNT(h.user_id)
          FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
          ) ft LEFT JOIN
          users u
          ON u.face_type = ft.face_type LEFT JOIN
          houses h
          ON h.user_id = u.id
          GROUP BY ft.face_type;


          To get NULL, just use UNION ALL:



          SELECT ft.face_type, COUNT(h.user_id)
          FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
          UNION ALL
          SELECT NULL
          ) ft LEFT JOIN
          users u
          ON u.face_type = ft.face_type LEFT JOIN
          houses h
          ON h.user_id = u.id
          GROUP BY ft.face_type;


          Of course, the = will not every match. If that is possible, then you want to change the JOIN condition to u.face_type is not distinct from ft.face_type.






          share|improve this answer























          • That would not include a row for 'null' face_type tho. As in, NULL is not part of the ENUM, but I want to have a row that counts for users who don't have face_type (and if all users have a face_type I still want the NULL row to be there, stating that users with no face_type have no houses).
            – Hommer Smith
            2 days ago










          • Is there a way to prepend/append NULL into enum_range(NULL::face_type)?
            – Hommer Smith
            2 days ago












          • What does it mean 'the = will not every match'?
            – Hommer Smith
            yesterday










          • This is not working as expected. It is not counting the users where face_type is NULL.
            – Hommer Smith
            yesterday












          • Now I understand your comment. THanks it works!
            – Hommer Smith
            yesterday



















          0














          A LEFT JOIN starting from the ENUM and going to users and houses will allow you to recover totals for each enumerated value. To also display the NULL face types, you can use a UNION query.



          SELECT 
          ft.face_type,
          COUNT(ho.user_id) as cnt
          FROM
          (SELECT unnest(enum_range(NULL::face_type)) AS face_types) ft
          LEFT JOIN users us ON us.face_type = ft.fact_type
          LEFT JOIN houses ho ON ho.user_id = us.id
          GROUP BY ft.face_type
          UNION
          SELECT
          null,
          COUNT(ho.user_id)
          FROM houses ho
          INNER JOIN users us ON ho.user_id = us.id AND us.face_type IS NULL
          ORDER BY cnt desc





          share|improve this answer





























            0














            to COUNT(houses.*)



            SELECT face_type.type, COUNT(houses.*)
            FROM (SELECT unnest(enum_range(NULL::face_type))) AS face_type(type)
            FULL JOIN users ON users.face_type=face_type.type
            LEFT JOIN houses ON houses.user_id = users.id
            GROUP BY face_type.type





            share|improve this answer























            • Why the COALESCE?
              – Hommer Smith
              yesterday










            • Oh, yeah! Perhaps it is unnecessary for this query. Edited...
              – Sergey Gershkovich
              yesterday













            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53944250%2fcount-for-all-values-of-enum-in-postgresql%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            You can use LEFT JOIN:



            SELECT ft.face_type, COUNT(h.user_id)
            FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
            ) ft LEFT JOIN
            users u
            ON u.face_type = ft.face_type LEFT JOIN
            houses h
            ON h.user_id = u.id
            GROUP BY ft.face_type;


            To get NULL, just use UNION ALL:



            SELECT ft.face_type, COUNT(h.user_id)
            FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
            UNION ALL
            SELECT NULL
            ) ft LEFT JOIN
            users u
            ON u.face_type = ft.face_type LEFT JOIN
            houses h
            ON h.user_id = u.id
            GROUP BY ft.face_type;


            Of course, the = will not every match. If that is possible, then you want to change the JOIN condition to u.face_type is not distinct from ft.face_type.






            share|improve this answer























            • That would not include a row for 'null' face_type tho. As in, NULL is not part of the ENUM, but I want to have a row that counts for users who don't have face_type (and if all users have a face_type I still want the NULL row to be there, stating that users with no face_type have no houses).
              – Hommer Smith
              2 days ago










            • Is there a way to prepend/append NULL into enum_range(NULL::face_type)?
              – Hommer Smith
              2 days ago












            • What does it mean 'the = will not every match'?
              – Hommer Smith
              yesterday










            • This is not working as expected. It is not counting the users where face_type is NULL.
              – Hommer Smith
              yesterday












            • Now I understand your comment. THanks it works!
              – Hommer Smith
              yesterday
















            0














            You can use LEFT JOIN:



            SELECT ft.face_type, COUNT(h.user_id)
            FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
            ) ft LEFT JOIN
            users u
            ON u.face_type = ft.face_type LEFT JOIN
            houses h
            ON h.user_id = u.id
            GROUP BY ft.face_type;


            To get NULL, just use UNION ALL:



            SELECT ft.face_type, COUNT(h.user_id)
            FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
            UNION ALL
            SELECT NULL
            ) ft LEFT JOIN
            users u
            ON u.face_type = ft.face_type LEFT JOIN
            houses h
            ON h.user_id = u.id
            GROUP BY ft.face_type;


            Of course, the = will not every match. If that is possible, then you want to change the JOIN condition to u.face_type is not distinct from ft.face_type.






            share|improve this answer























            • That would not include a row for 'null' face_type tho. As in, NULL is not part of the ENUM, but I want to have a row that counts for users who don't have face_type (and if all users have a face_type I still want the NULL row to be there, stating that users with no face_type have no houses).
              – Hommer Smith
              2 days ago










            • Is there a way to prepend/append NULL into enum_range(NULL::face_type)?
              – Hommer Smith
              2 days ago












            • What does it mean 'the = will not every match'?
              – Hommer Smith
              yesterday










            • This is not working as expected. It is not counting the users where face_type is NULL.
              – Hommer Smith
              yesterday












            • Now I understand your comment. THanks it works!
              – Hommer Smith
              yesterday














            0












            0








            0






            You can use LEFT JOIN:



            SELECT ft.face_type, COUNT(h.user_id)
            FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
            ) ft LEFT JOIN
            users u
            ON u.face_type = ft.face_type LEFT JOIN
            houses h
            ON h.user_id = u.id
            GROUP BY ft.face_type;


            To get NULL, just use UNION ALL:



            SELECT ft.face_type, COUNT(h.user_id)
            FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
            UNION ALL
            SELECT NULL
            ) ft LEFT JOIN
            users u
            ON u.face_type = ft.face_type LEFT JOIN
            houses h
            ON h.user_id = u.id
            GROUP BY ft.face_type;


            Of course, the = will not every match. If that is possible, then you want to change the JOIN condition to u.face_type is not distinct from ft.face_type.






            share|improve this answer














            You can use LEFT JOIN:



            SELECT ft.face_type, COUNT(h.user_id)
            FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
            ) ft LEFT JOIN
            users u
            ON u.face_type = ft.face_type LEFT JOIN
            houses h
            ON h.user_id = u.id
            GROUP BY ft.face_type;


            To get NULL, just use UNION ALL:



            SELECT ft.face_type, COUNT(h.user_id)
            FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
            UNION ALL
            SELECT NULL
            ) ft LEFT JOIN
            users u
            ON u.face_type = ft.face_type LEFT JOIN
            houses h
            ON h.user_id = u.id
            GROUP BY ft.face_type;


            Of course, the = will not every match. If that is possible, then you want to change the JOIN condition to u.face_type is not distinct from ft.face_type.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday

























            answered 2 days ago









            Gordon Linoff

            757k35291399




            757k35291399












            • That would not include a row for 'null' face_type tho. As in, NULL is not part of the ENUM, but I want to have a row that counts for users who don't have face_type (and if all users have a face_type I still want the NULL row to be there, stating that users with no face_type have no houses).
              – Hommer Smith
              2 days ago










            • Is there a way to prepend/append NULL into enum_range(NULL::face_type)?
              – Hommer Smith
              2 days ago












            • What does it mean 'the = will not every match'?
              – Hommer Smith
              yesterday










            • This is not working as expected. It is not counting the users where face_type is NULL.
              – Hommer Smith
              yesterday












            • Now I understand your comment. THanks it works!
              – Hommer Smith
              yesterday


















            • That would not include a row for 'null' face_type tho. As in, NULL is not part of the ENUM, but I want to have a row that counts for users who don't have face_type (and if all users have a face_type I still want the NULL row to be there, stating that users with no face_type have no houses).
              – Hommer Smith
              2 days ago










            • Is there a way to prepend/append NULL into enum_range(NULL::face_type)?
              – Hommer Smith
              2 days ago












            • What does it mean 'the = will not every match'?
              – Hommer Smith
              yesterday










            • This is not working as expected. It is not counting the users where face_type is NULL.
              – Hommer Smith
              yesterday












            • Now I understand your comment. THanks it works!
              – Hommer Smith
              yesterday
















            That would not include a row for 'null' face_type tho. As in, NULL is not part of the ENUM, but I want to have a row that counts for users who don't have face_type (and if all users have a face_type I still want the NULL row to be there, stating that users with no face_type have no houses).
            – Hommer Smith
            2 days ago




            That would not include a row for 'null' face_type tho. As in, NULL is not part of the ENUM, but I want to have a row that counts for users who don't have face_type (and if all users have a face_type I still want the NULL row to be there, stating that users with no face_type have no houses).
            – Hommer Smith
            2 days ago












            Is there a way to prepend/append NULL into enum_range(NULL::face_type)?
            – Hommer Smith
            2 days ago






            Is there a way to prepend/append NULL into enum_range(NULL::face_type)?
            – Hommer Smith
            2 days ago














            What does it mean 'the = will not every match'?
            – Hommer Smith
            yesterday




            What does it mean 'the = will not every match'?
            – Hommer Smith
            yesterday












            This is not working as expected. It is not counting the users where face_type is NULL.
            – Hommer Smith
            yesterday






            This is not working as expected. It is not counting the users where face_type is NULL.
            – Hommer Smith
            yesterday














            Now I understand your comment. THanks it works!
            – Hommer Smith
            yesterday




            Now I understand your comment. THanks it works!
            – Hommer Smith
            yesterday













            0














            A LEFT JOIN starting from the ENUM and going to users and houses will allow you to recover totals for each enumerated value. To also display the NULL face types, you can use a UNION query.



            SELECT 
            ft.face_type,
            COUNT(ho.user_id) as cnt
            FROM
            (SELECT unnest(enum_range(NULL::face_type)) AS face_types) ft
            LEFT JOIN users us ON us.face_type = ft.fact_type
            LEFT JOIN houses ho ON ho.user_id = us.id
            GROUP BY ft.face_type
            UNION
            SELECT
            null,
            COUNT(ho.user_id)
            FROM houses ho
            INNER JOIN users us ON ho.user_id = us.id AND us.face_type IS NULL
            ORDER BY cnt desc





            share|improve this answer


























              0














              A LEFT JOIN starting from the ENUM and going to users and houses will allow you to recover totals for each enumerated value. To also display the NULL face types, you can use a UNION query.



              SELECT 
              ft.face_type,
              COUNT(ho.user_id) as cnt
              FROM
              (SELECT unnest(enum_range(NULL::face_type)) AS face_types) ft
              LEFT JOIN users us ON us.face_type = ft.fact_type
              LEFT JOIN houses ho ON ho.user_id = us.id
              GROUP BY ft.face_type
              UNION
              SELECT
              null,
              COUNT(ho.user_id)
              FROM houses ho
              INNER JOIN users us ON ho.user_id = us.id AND us.face_type IS NULL
              ORDER BY cnt desc





              share|improve this answer
























                0












                0








                0






                A LEFT JOIN starting from the ENUM and going to users and houses will allow you to recover totals for each enumerated value. To also display the NULL face types, you can use a UNION query.



                SELECT 
                ft.face_type,
                COUNT(ho.user_id) as cnt
                FROM
                (SELECT unnest(enum_range(NULL::face_type)) AS face_types) ft
                LEFT JOIN users us ON us.face_type = ft.fact_type
                LEFT JOIN houses ho ON ho.user_id = us.id
                GROUP BY ft.face_type
                UNION
                SELECT
                null,
                COUNT(ho.user_id)
                FROM houses ho
                INNER JOIN users us ON ho.user_id = us.id AND us.face_type IS NULL
                ORDER BY cnt desc





                share|improve this answer












                A LEFT JOIN starting from the ENUM and going to users and houses will allow you to recover totals for each enumerated value. To also display the NULL face types, you can use a UNION query.



                SELECT 
                ft.face_type,
                COUNT(ho.user_id) as cnt
                FROM
                (SELECT unnest(enum_range(NULL::face_type)) AS face_types) ft
                LEFT JOIN users us ON us.face_type = ft.fact_type
                LEFT JOIN houses ho ON ho.user_id = us.id
                GROUP BY ft.face_type
                UNION
                SELECT
                null,
                COUNT(ho.user_id)
                FROM houses ho
                INNER JOIN users us ON ho.user_id = us.id AND us.face_type IS NULL
                ORDER BY cnt desc






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered yesterday









                GMB

                3,814519




                3,814519























                    0














                    to COUNT(houses.*)



                    SELECT face_type.type, COUNT(houses.*)
                    FROM (SELECT unnest(enum_range(NULL::face_type))) AS face_type(type)
                    FULL JOIN users ON users.face_type=face_type.type
                    LEFT JOIN houses ON houses.user_id = users.id
                    GROUP BY face_type.type





                    share|improve this answer























                    • Why the COALESCE?
                      – Hommer Smith
                      yesterday










                    • Oh, yeah! Perhaps it is unnecessary for this query. Edited...
                      – Sergey Gershkovich
                      yesterday


















                    0














                    to COUNT(houses.*)



                    SELECT face_type.type, COUNT(houses.*)
                    FROM (SELECT unnest(enum_range(NULL::face_type))) AS face_type(type)
                    FULL JOIN users ON users.face_type=face_type.type
                    LEFT JOIN houses ON houses.user_id = users.id
                    GROUP BY face_type.type





                    share|improve this answer























                    • Why the COALESCE?
                      – Hommer Smith
                      yesterday










                    • Oh, yeah! Perhaps it is unnecessary for this query. Edited...
                      – Sergey Gershkovich
                      yesterday
















                    0












                    0








                    0






                    to COUNT(houses.*)



                    SELECT face_type.type, COUNT(houses.*)
                    FROM (SELECT unnest(enum_range(NULL::face_type))) AS face_type(type)
                    FULL JOIN users ON users.face_type=face_type.type
                    LEFT JOIN houses ON houses.user_id = users.id
                    GROUP BY face_type.type





                    share|improve this answer














                    to COUNT(houses.*)



                    SELECT face_type.type, COUNT(houses.*)
                    FROM (SELECT unnest(enum_range(NULL::face_type))) AS face_type(type)
                    FULL JOIN users ON users.face_type=face_type.type
                    LEFT JOIN houses ON houses.user_id = users.id
                    GROUP BY face_type.type






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited yesterday

























                    answered yesterday









                    Sergey Gershkovich

                    895




                    895












                    • Why the COALESCE?
                      – Hommer Smith
                      yesterday










                    • Oh, yeah! Perhaps it is unnecessary for this query. Edited...
                      – Sergey Gershkovich
                      yesterday




















                    • Why the COALESCE?
                      – Hommer Smith
                      yesterday










                    • Oh, yeah! Perhaps it is unnecessary for this query. Edited...
                      – Sergey Gershkovich
                      yesterday


















                    Why the COALESCE?
                    – Hommer Smith
                    yesterday




                    Why the COALESCE?
                    – Hommer Smith
                    yesterday












                    Oh, yeah! Perhaps it is unnecessary for this query. Edited...
                    – Sergey Gershkovich
                    yesterday






                    Oh, yeah! Perhaps it is unnecessary for this query. Edited...
                    – Sergey Gershkovich
                    yesterday




















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53944250%2fcount-for-all-values-of-enum-in-postgresql%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Mossoró

                    Error while reading .h5 file using the rhdf5 package in R

                    Pushsharp Apns notification error: 'InvalidToken'