SQL计数DISTINCT ONCE user_id多个属性

时间:2017-07-12 18:58:24

标签: sql postgresql

你好,我无法在以下情况下取得好成绩:

我有一张像这样的表:

UserID | Label
-------- ------
1      | Private
1      | Public
2      | Private
3      | Hidden
4      | Public
5      | Hidden

如果用户有以下指定,我希望发生以下情况:

私人和隐藏受到同样的打击:让我们说商务
公众:BtoC
公共和私人和/或隐藏:双方

所以最后我有count(DISTINCT UserID)

Business         3
BtoC             1
both             1

我尝试使用CASE WHEN,但它不起作用我的当前总查询如下所示:

SELECT gen_month,
       count(DISTINCT cu.id) as leads,
        a.label
FROM generate_series(DATE_TRUNC('month', CURRENT_DATE::date - 96*INTERVAL '1 month'), CURRENT_DATE::date, '1 month') m(gen_month)
LEFT OUTER JOIN company_user AS cu
  ON (date_trunc('month', cu.creation_date) = date_trunc('month', gen_month))
LEFT JOIN user u
  ON u.user_id = cu.id
LEFT join user_account_status as uas
on cu.id = uas.user_id
LEFT JOIN account as a
on uas.account_id = a.id
where gen_month >= DATE_TRUNC('month',NOW() - INTERVAL '5 months')
group by  m.gen_month, a.label
order by gen_month

所以现在我的主要问题是计数出现在每个属性中一次。 如何使用户ID仅在条件情况下计数一次当用户_id出现时公共和(私有或隐藏)那么计数(DISTINCT user_id)为两者?

另外:它的mySQL mariaDB和postgreSQL。但首先我会对Postgres感到满意

2 个答案:

答案 0 :(得分:0)

这不是在您的总查询中实现的,但是对于每个类别的用户计数,您可以:

is_admin

答案 1 :(得分:0)

with 
  my_table(user_id, label) as (values
    (1,'Private'),
    (1,'Public'),
    (2,'Private'),
    (3,'Hidden'),
    (4,'Public'),
    (5,'Hidden')),
  t as (
    select
      user_id,
      string_agg('{'||label||'}', '') as labels
    from my_table
    group by user_id),
  tt as (
    select
      user_id,
      labels,
      case
        when
          position('{Public}' in labels) > 0 and (position('{Private}' in labels) > 0 or position('{Hidden}' in labels) > 0) then 'Both'
        when
          position('{Private}' in labels) > 0 or position('{Hidden}' in labels) > 0 then 'Business'
        when
          position('{Public}' in labels) > 0 then 'BtoC'
      end as kind
    from t)
select kind, count(*) from tt group by kind;

对于MariaDB,使用GROUP_CONCAT()而不是PostgreSQL string_agg()

请注意,case语句按出现顺序检查条件,并返回第一个满足条件的值。

PS:使用PostgreSQL的数组,条件会更优雅。