加入来自不同列的相同 table 的多个计数?

Joining multiple counts on the same table, from different columns?

我觉得这应该很容易,但已经晚了,我正在挣扎。

说(在 oracle 12 db 中)我有一个 table,它表示在不同的事件期间,哪个员工在酒吧中担任什么角色,如下所示:

+----------+----------+-------+------------+----------+
| event_id | bar      | doors | cloak_room | keg_room |
+----------+----------+-------+------------+----------+
| 2        | bob      | bill  | john       | mary     |
+----------+----------+-------+------------+----------+
| 3        | bob      | bill  | mary       | kev      |
+----------+----------+-------+------------+----------+
| 4        | bob      | john  | louise     | mary     |
+----------+----------+-------+------------+----------+
| 5        | kyle     | kev   | sarah      | louise   |
+----------+----------+-------+------------+----------+
| 6        | jennifer | bob   | jay        | john     |
+----------+----------+-------+------------+----------+
| 7        | john     | bill  | mary       | steve    |
+----------+----------+-------+------------+----------+ 

我想统计每个员工完成了多少事件,如下所示:

+-------+--------+
| count | person |
+-------+--------+
| 4     | bob    |
+-------+--------+
| 4     | john   |
+-------+--------+
| 3     | bill   |
+-------+--------+
| 3     | mary   |
+-------+--------+
| 2     | kev    |
+-------+--------+
| 2     | louise |
+-------+--------+
| 1     | jay    |
+-------+--------+
| 1     | steve  |
+-------+--------+ 

我们在这里看到 bob 的计数为 4 - 因为他与 4 个不同的 event_id 关联:3 个作为酒保,1 个作为门卫。

(假设没有两个员工同名,也没有人可以同时做两份工作)

我该怎么做?

一个 'role' 很明显:

select count(event_id), bar group by bar

但是有没有一种优雅的方法可以对所有列执行此操作 - 无需完全连接和字符串连接?

谢谢!

您应该更改数据结构,因此每个 event/person/role 一行。那么你可以只使用聚合。

您也可以在查询中执行此操作:

select who, count(*)
from (select event_id, 'bar' as job, bar as who from t union all
      select event_id, 'doors' as job, doors as who from t union all
      select event_id, 'cloak_room' as job, cloak_room as who from t union all
      select event_id, 'keg_room' as job, keg_room as who from t
     ) jw
group by who;

如果某人可以在一次活动中同时担任多项工作,则使用 count(distinct event_id)

编辑:

我看到您使用的是 Oracle 12c。然后使用横向join/cross apply:

select who, count(*)
from t cross apply
     (select t.event_id, 'bar' as job, t.bar as who from dual union all
      select t.event_id, 'doors' as job, t.doors as who from dual from dual union all
      select event_id, 'cloak_room' as job, cloak_room as who from dual union all
      select t.event_id, 'keg_room' as job, t.keg_room as who from dual
     ) jw
group by who;

您可以 count 嵌套内部查询中的字符串列,然后 sum 它们 up 外面有你想要的 order :

SELECT sum(count) count, person
  FROM
(
 SELECT count(event_id) count, bar person FROM mytable GROUP BY bar UNION ALL
 --> P.S. Only aliasing as "person" is enough in this upper "select" for all 
 --> four "select" statements inside the parentheses.
 SELECT count(event_id)      , doors      FROM mytable GROUP BY doors UNION ALL
 SELECT count(event_id)      , cloak_room FROM mytable GROUP BY cloak_room UNION ALL
 SELECT count(event_id)      , keg_room   FROM mytable GROUP BY keg_room
)
GROUP BY person
ORDER BY 1 desc, 2;

COUNT   PERSON
   4    bob
   4    john
   3    bill
   3    mary
   2    kev
   2    louise
   1    jay
   1    jennifer
   1    kyle
   1    mary2
   1    sarah
   1    steve

SQL Fiddle Demo