Is it possible to reuse the result from a subquery in a subsequent subquery when creating a view in postgresql?
For example I have the following two tables:
CREATE TABLE application
(
id INT PRIMARY KEY,
name CHARACTER VARYING(255)
);
CREATE TABLE application_user
(
id INT PRIMARY KEY,
application_id INT REFERENCES application (id) ON DELETE CASCADE,
active BOOLEAN
);
-- some sample data
INSERT INTO application (id, name) VALUES
(10, 'application1'),
(20, 'application2'),
(30, 'application3');
INSERT INTO application_user (id, application_id, active) VALUES
(1, 10, true),
(2, 10, false),
(3, 20, false),
(4, 20, false),
(5, 20, false);
The view that I need looks (right now) as follows:
CREATE VIEW application_stats AS
SELECT a.name,
(SELECT COUNT(1) FROM application_user u
WHERE a.id = u.application_id) AS users,
(SELECT COUNT(1) FROM application_user u
WHERE a.id = u.application_id AND u.active = true) AS active_users
FROM application a;
This does give me the correct result:
name users active_users application1 2 1 application2 3 0 application3 0 0
However it is also pretty inefficient since I'm using two times almost the same query and ideally I would like to reuse the result from the first query. Is there an efficient way to do this?
This would normally be expressed as a join
/ group by
:
SELECT a.name, COUNT(au.application_id) as users,
SUM( (au.active = true)::int) as active_users
FROM application a LEFT JOIN
application_user au
ON a.name = au.application_id
GROUP BY a.name;
I'm rather surprised that application
doesn't have a serial
primary key. But because you are using name
, perhaps the join
is not needed at all:
SELECT au.application_id, COUNT(*) as users,
SUM( (au.active = true)::int) as active_users
FROM application_user au
GROUP BY au.application_id;
This will return applications that have at least one server.
You should join the two tables, group by application_id
and use count
with a FILTER (WHERE ...)
clause to count only the rows you want:
CREATE VIEW application_stats AS
SELECT a.name
count(*) AS users,
count(*) FILTER (WHERE u.active) AS active_users
FROM application a
LEFT JOIN application_user u ON a.id = u.application_id
GROUP BY a.id;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.