Count for all values of enum in PostgreSQL
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
add a comment |
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
add a comment |
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
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
sql postgresql enums group-by count
edited 2 days ago
GMB
3,814519
3,814519
asked 2 days ago
Hommer Smith
8,76638112206
8,76638112206
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
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.
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 intoenum_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
add a comment |
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
add a comment |
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
Why the COALESCE?
– Hommer Smith
yesterday
Oh, yeah! Perhaps it is unnecessary for this query. Edited...
– Sergey Gershkovich
yesterday
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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 intoenum_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
add a comment |
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.
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 intoenum_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
add a comment |
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.
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.
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 intoenum_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
add a comment |
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 intoenum_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
add a comment |
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
add a comment |
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
add a comment |
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
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
answered yesterday
GMB
3,814519
3,814519
add a comment |
add a comment |
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
Why the COALESCE?
– Hommer Smith
yesterday
Oh, yeah! Perhaps it is unnecessary for this query. Edited...
– Sergey Gershkovich
yesterday
add a comment |
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
Why the COALESCE?
– Hommer Smith
yesterday
Oh, yeah! Perhaps it is unnecessary for this query. Edited...
– Sergey Gershkovich
yesterday
add a comment |
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
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
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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