我有users
表
Table "public.users"
Column | Type | Modifiers
--------+---------+-----------
user_id | integer |
style | boolean |
id | integer |
和access_rights
表
Table "public.access_rights"
Column | Type | Modifiers
--------+---------+-----------
user_id | integer |
id | integer |
我有一个查询在访问权限上加入用户,我想计算样式列中值为true的值。
从这个回答:postgresql - sql - count of `true` values,我尝试了
SELECT COUNT( CASE WHEN style THEN 1 ELSE null END )
from users
join access_rights on access_rights.user_id = users.user_id
;
但是,当用户有多个access_rights行时,它会计算重复值。如何在使用连接时仅计算一次值?
答案 0 :(得分:1)
如果您对style IS TRUE
中至少 1行(access_rights
)的用户数感兴趣,请在加入前汇总access_rights
:
SELECT count(style OR NULL) AS style_ct
FROM users
JOIN (
SELECT user_id, bool_or(style) AS style
FROM access_rights
GROUP BY 1
) u USING (user_id);
使用JOIN
,因为access_rights
中没有任何条目的用户在这种情况下不会计数。
使用聚合函数bool_or()
。
或更简单:
SELECT count(*) AS style_ct
FROM (
SELECT user_id
FROM access_rights
GROUP BY 1
HAVING bool_or(style)
);
这假设外键强制引用完整性,因此access_rights.user_id
中没有users
没有相应的行。
同时假设NULL
中没有access_rights.user_id
值,这会使计数增加1 - 并且可以使用count(user_id)
代替count(*)
来抵消。
或(如果该假设不属实)请使用EXISTS
半连接:
SELECT count( EXISTS (
SELECT 1
FROM access_rights
WHERE user_id = u.user_id
AND style -- boolean value evaluates on its own
) OR NULL
)
FROM users u;
我正在使用true boolean
值的功能来简化计数和WHERE
子句。详细信息:
Compute percents from SUM() in the same SELECT sql query
答案 1 :(得分:1)
你可以这样做:
尝试这样的事情(每the documentation)
select sum( case style when TRUE then 1 else 0 end ) as style_count
from public.users u
join public.access_rights ar on ar.user_id = u.user_id
或者,考虑到您的问题陈述," 我想计算样式列中值为true的值",您可以这样做:
select count(*) as style_count
from public.users u
join public.access_rights ar on ar.user_id = u.user_id
where u.style = TRUE
编辑注意:
在重新阅读您的问题时,听起来您真正想要的是style
属性为true
并拥有访问权限的不同用户。你可以通过这个来达到目的:
select count(distinct u.user_id)
from public.users u
join public.access_rights ar on ar.user_id = u.user_id
where u.style = TRUE
;
到达那里的另一种方式是这样的:
select count(*)
from public.users u
where u.style = TRUE
and exists ( select *
from public.access_rights ar
where ar.user_id = u.user_id
)
我会投票支持后者,因为它更清楚地显示了你的意图。
答案 2 :(得分:1)
似乎每个人对这个问题都有不同的理解。这是我的
select
count(case when style then 1 end) as classic_case,
count(style or null) as boolean_count
from users u
where exists (
select 1
from access_rights
where user_id = u.user_id
)
它将计算具有access_rights的用户的真实总数。