从同一表中选择不同的计数

时间:2017-11-22 16:24:41

标签: oracle

我在Oracle DB上有T_LOCATION_DATA表,如下所示:

Person_ID | Location | Role
----------------------------
101         Delhi      Manager
102         Mumbai     Employee
103         Noida      Manager
104         Mumbai     Employee
105         Noida      Employee
106         Delhi      Manager
107         Mumbai     Manager
108         Delhi      Employee
109         Mumbai     Employee

另一张表是T_STATUS,其中包含以下数据:

Person_ID | Status
-------------------
101         Active
102         Active
103         Inactive
104         Active
105         Active
106         Inactive      
107         Active     
108         Active
109         Inactive

我正在努力获得活跃的员工和经理人数;按位置分组在一个查询中,以便结果如下:

Location  |   MANAGER COUNT |  EMPLOYEE COUNT
Delhi         1                1
Mumbai        1                1
Noida         0                1

我正在尝试以下查询,但没有结果:

select location, count (a.person_id) as MANAGER COUNT, 
                 count (b.person_id) as EMPLOYEE COUNT 
from   T_LOCATION_DATA a,T_LOCATION_DATA b 
where  a.person_id in (select person_id from t_status where status='Active')

......我迷路了

有人可以指导我吗?

1 个答案:

答案 0 :(得分:4)

根据您的数据,我会这样查询:

SELECT 
  Location,
  COUNT(CASE WHEN Role='Manager' THEN 1 END) as count_managers,
  COUNT(CASE WHEN Role='Employee' THEN 1 END) as count_employees,
  COUNT(*) count_everyone
FROM
  t_location_data l 
  INNER JOIN 
  t_status s
  ON
    l.person_id = s.person_id AND
    s.status = 'Active'
GROUP BY location

与SQL的区别:

我们转储了糟糕的旧连接语法(SELECT * FROM a,b WHERE a.id=b.id) - 请始终使用a JOIN b ON a.id = b.id

我们加入状态表,但我们只对活动状态表做了,因此我将其作为ON中的另一个子句。我可以把它放在WHERE中。使用INNER JOIN它没有任何区别。使用OUTER JOIN它可以产生很大的不同,就好像你写a LEFT JOIN b ON a.id = b.id WHERE b.id = 'active'会将LEFT JOIN转换回INNER JOIN行为,除非你创建了像WHERE b.id = 'active' OR b.id IS NULL这样的where子句 - 而且&# 39;只是丑陋。如果将常量的比较放在ON子句中,则可以跳过or ... is null丑陋

我们按地点分组,但我们不一定会计算所有内容。如果我们计算CASE WHEN role = 'Manager' THEN ...的结果,那么为管理器生成1的情况,并且它为非管理器生成NULL(我没有为else指定任何内容;这是设计行为的在这种情况下的情况)。这个数字也不一定是1;它可以是'a'Role;任何非空的东西。 COUNT将任何非null值作为1计算,将null作为0计算。以下是等效的,选择对您更有意义的值:

COUNT(CASE WHEN Role='Employee' THEN 1 END) as count_employees,
COUNT(CASE WHEN Role='Employee' THEN 'a' END) as count_employees,
COUNT(CASE WHEN Role='Employee' THEN role END) as count_employees,
COUNT(CASE WHEN Role='Employee' THEN role ELSE null END) as count_employees,
SUM(CASE WHEN Role='Employee' THEN 1 ELSE 0 END) as count_employees,

它们都作为计数工作,但在SUM情况下,如果要将输出数作为计数,则确实必须使用1和0。实际上,0是可选的,因为SUM不会对空值求和(但正如下面的算法指出的那样,如果你没有将ELSE设为0,那么当有0个项时,SUM方法会产生NULL,而不是一个0.这对你来说是有帮助的还是阻碍你的决定

我还不清楚经理是否也是员工。对我来说,他们可能不是你。我添加了一个COUNT(*)字面计算该位置的每个人。任何差异意味着count_employees + count_managers!= count_everyone意味着表中还有另一个角色,而不是经理或员工..选择你的毒药

COUNT/SUM(CASE WHEN...)模式对于转换数据非常有用 - 一个PIVOT操作。它需要一列数据:

Manager
Employee
Manager

并将其分为两列,用于计数值:

Manager Employee
2       1

您可以根据需要多次扩展它。如果您有10个角色,则生成10个案例,结果将有10个列,并且具有分组计数。数据从row-ar表示转换为column-ar表示