Sql 创建视图时重用子查询的结果

Sql 创建视图时重用子查询的结果,sql,postgresql,Sql,Postgresql,在postgresql中创建视图时,是否可以在后续子查询中重用子查询的结果 例如,我有以下两个表: 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 DELE

在postgresql中创建视图时,是否可以在后续子查询中重用子查询的结果

例如,我有以下两个表:

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);
我需要的视图(现在)如下所示:

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;
这确实给了我正确的结果:

name users active_users application1 2 1 application2 3 0 application3 0 0 名称用户活动用户 应用程序1 2 1 应用程序2 3 0 应用程序3 0
然而,这也是非常低效的,因为我使用了两次几乎相同的查询,理想情况下,我希望重用第一次查询的结果。有没有一种有效的方法可以做到这一点?

这通常表示为一个
加入
/
分组:

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;
我很惊讶
应用程序
没有
串行
主键。但是由于您使用的是
名称
,因此可能根本不需要
加入

SELECT au.application_id, COUNT(*) as users,
       SUM( (au.active = true)::int) as active_users
FROM application_user au
GROUP BY au.application_id;

这将返回至少有一台服务器的应用程序。

您应该连接两个表,按
application\u id
分组,并使用
count
筛选器(其中…
子句)仅计算所需的行:

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;

似乎是CTE(带查询的)的一个很好的用例。为了简洁起见,我排除了第一个表的序列id,但我发现这会带来不同,我的缺点。然而,我尝试了您的第一个解决方案,但没有得到“application3”活动用户的结果(application3没有任何用户,因此应该显示用户:0,活动用户:0)啊,我猜您的意思是将
计数(au.active=true)为活动用户
,然后它就可以工作了。问题是,这仍然比我正在使用的重复联接慢,因为我不使用左联接。然而,我问的问题可能不清楚这一点,所以我想我应该问一个新的问题。