SQL 查询以获取每个经理下的员工的递归计数

Posted

技术标签:

【中文标题】SQL 查询以获取每个经理下的员工的递归计数【英文标题】:SQL Query to get recursive count of employees under each manager 【发布时间】:2013-10-30 17:52:53 【问题描述】:

我正在寻找一个 SQL 查询来获取每个经理或其他表中的一些经理下的 Employee 的递归计数。

表结构是:

Emp_Table

Emp_id Manager_id
1         1
2         1
3         1
4         3
5         3
6         5
7         5
8         7
9         7
10        7

执行表:

此表只是此处可用的选定经理。我需要统计这位经理下的每个员工的人数

Manager_id
     1
     4
     7
     8

我正在寻找以下输出

Manager_ID   Count_of_Employees
     1             9
     4             0
     7             3 
     8             0

请注意,您的回答仅提供了我收到的每位经理的直接下属员工人数。但我正在寻找经理的递归员工报告。在我上面的示例中,根据您的查询,我将获得 Manager_id 1 和员工人数为 3,但我正在寻找输出为 9。提前致谢!

感谢您的所有回复。我终于得到了查询。请找到我的答案。

【问题讨论】:

@DanAndrews.. 我不是在寻找以下查询。我清楚地说我正在寻找名单下的雇员的recruitative aunt。我错过了一些东西。只是想得到别人的帮助。但是有人标记了降级的问题。 什么? “我正在寻找一个 SQL 查询来获取 Employee 的计数......” 通常在 *** 上,人们会先发布他们尝试过的内容。从那里,人们可以提供帮助。如果你收到的答案不是你想要的,那么也许你需要看看你在问什么。 @Dhana:你可以看到每个人都对此感到困惑,首先是不清楚。 @DanAndrews.. 很抱歉给您带来麻烦。在我的示例输出中,我清楚地发布了带有递归计数的输出。谢谢! 【参考方案1】:

首先,重要说明Emp_Table 的第一行,Emp_id==Manager_Id==1 不仅没有意义,还会导致无限递归 。我建议你删除它。

然而,为了提供答案,我首先创建了一个视图来消除此类无效条目,并使用 that 而不是Emp_Table

create view valid_mng as 
select Emp_Id,Manager_id from Emp_Table
where Emp_Id<>Manager_Id

所以它归结为以下,在递归 CTE 的帮助下:

With cte as (
  select Emp_Id,Manager_id from valid_mng
  union all
  select c.Emp_Id,e.Manager_Id 
  from cte c join valid_mng e on (c.Manager_Id=e.Emp_Id)
  )

select m.Manager_Id,count(e.Emp_Id) as Count_of_Employees
from [Execute] m
left join cte e on (e.Manager_Id=m.Manager_Id)
group by m.Manager_Id

如果您最终删除了有问题的行,或者最好按照 HABO 的建议设置 Manager_Id=NULL,只需忽略 valid_mng 视图并将其替换为各处的 Emp_Table。 p>

另外附注:Execute 是 MSSQL 中的保留字。避免在用户对象命名中使用保留字始终是一个好习惯

【讨论】:

@Dhana - 通常将经理置于由 NULL 的 Manager_Id 表示的层次结构(或食物链)的顶部。它可以避免卡在管理自己的经理身上。 @geomagas.. 这对我有用。谢谢! @geomagas.. 你的答案执行时间太长了。我修改了一些东西来更改代码以使其完美运行。我为我的问题提交了最佳答案。请看一看。无论如何,非常感谢您的工作。 @Dhana:我在你的问题中没有看到任何性能要求。 @geomagas .. 干得好。我接受你的回答是好的。实时我有十万行。如果可以的话,你能帮我提高这个查询的性能吗?【参考方案2】:

类似于geomagas,但不是从中派生出来的。它递归地构建管理报告树,然后对其进行汇总。

declare @Emp_Table as Table ( Emp_id Int Identity, Manager_id Int );
insert into @Emp_Table ( Manager_id ) values
  ( 1 ), ( 1 ), ( 1 ), ( 3 ), ( 3 ), ( 5 ), ( 5 ), ( 7 ), ( 7 ), ( 7 );
select * from @Emp_Table;

declare @Execute as Table ( Manager_id Int );
insert into @Execute ( Manager_id ) values
  ( 1 ), ( 4 ), ( 7 ), ( 8 );
select * from @Execute;

with Reports as (
  select Manager_id, Emp_id, Manager_id as Top_Manager_id
    from @Emp_Table where Manager_id <> Emp_id
  union all
  select ET.Manager_id, ET.Emp_id, R.Top_Manager_id
    from Reports as R inner join
      @Emp_Table as ET on ET.Manager_id = R.Emp_id
  )
  select E.Manager_id, Count( R.Emp_id ) as Count_Of_Employees
    from @Execute as E left outer join
      Reports as R on R.Top_Manager_id = E.Manager_id
    group by E.Manager_id;

【讨论】:

【参考方案3】:

您可以使用分组方式:

SELECT count(*) AS Count_of_Employees,
    Manager_ID
FROM yourtable
GROUP BY Manager_ID

【讨论】:

@Sadek.. 谢谢!您的答案仅给出了我得到的每位经理的直接下属员工人数。布特我正在寻找与经理一起重复的员工报告。在我上面的示例中,根据您的查询,我将得到 Manager_id 1 计数为 3,但我正在寻找输出为 9。感谢是 Advance!【参考方案4】:

我遇到了这样的问题,查找属于最高经理的员工人数

表:

CREATE TABLE employees (
  id INTEGER PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  managerId INTEGER,
  FOREIGN KEY (managerId) REFERENCES employees(id)
);

INSERT INTO employees(id, name, managerId) VALUES(1, 'Rob', null);
INSERT INTO employees(id, name, managerId) VALUES(2, 'Tom', null);
INSERT INTO employees(id, name, managerId) VALUES(3, 'Roger', 1);
INSERT INTO employees(id, name, managerId) VALUES(4, 'Victor', 3);
INSERT INTO employees(id, name, managerId) VALUES(5, 'John', 4);
INSERT INTO employees(id, name, managerId) VALUES(6, 'Shawn', 2);

-- Expected output
-- Id    EmployeeCount
-- --------------------
-- 1          3
-- 2          1

我的解决方案是:

WITH EmployeeCTE
     AS (SELECT e.id, e.managerid as topmanager
         FROM   employees e, employees m
         WHERE  e.managerid = m.id AND m.managerid IS NULL
         UNION ALL
         SELECT e.id, mgr.topmanager
         FROM   employees e, EmployeeCTE mgr
         WHERE  e.managerid = mgr.id)
SELECT topmanager, count(*)
FROM   EmployeeCTE AS u
GROUP BY topmanager;

【讨论】:

【参考方案5】:
SELECT Manager_id, COUNT(Emp_id) AS Count_of_Employees
FROM Emp_Table
WHERE Manager_id IN (1,4,7,8)
GROUP BY Manager_id

【讨论】:

谢谢@marc_s,你能告诉我你是如何格式化的吗?每次我尝试给出 SQL 格式时,结果都不正确。 如果您发布代码、XML 或数据示例,只需在文本编辑器中突出显示这些行,然后单击编辑器工具栏上的“代码示例”按钮 ( )(左起第三个,第二组图标)以很好地格式化和语法突出显示它。或突出显示行并按 Ctrl-K 进行格式化。 再次感谢@marc_s! 另外,你可能想要使用这个(如果你买不起 RedGate 的工具)architectshack.com/PoorMansTSqlFormatter.ashx【参考方案6】:

您可能想尝试以下方法:

SELECT MANAGER_ID,
    COUNT(EMP_ID) AS EMP_COUNT
FROM EMP_TABLE
GROUP BY MANAGER_ID

【讨论】:

【参考方案7】:
SELECT manager_id,
    count(DISTINCT emp_id)
FROM emp_table
GROUP BY manager_id

UNION

SELECT manager_id,
    0
FROM execute_table
WHERE manager_id NOT IN (
        SELECT manager_id
        FROM emp_table
        )

【讨论】:

【参考方案8】:
SELECT COUNT(Emp_id) county,
    Manager_id
FROM Emp_Table
GROUP BY Manager_id

【讨论】:

【参考方案9】:
SELECT Manager_Id,
    Count(Employee_Id)
FROM Emp_Table
WHERE Manager_Id IN (
        SELECT Manager_Id
        FROM Manager
        )
GROUP BY Manager_Id

【讨论】:

【参考方案10】:

这是一个简单的 pl sql 查询,用于获取经理下的员工总数(直接和间接)。

select empno , ename, 
(
select count(empno) from emp
start with ename = a.ename
connect by prior empno = mgr
) as under 
from emp a;

【讨论】:

以上是关于SQL 查询以获取每个经理下的员工的递归计数的主要内容,如果未能解决你的问题,请参考以下文章

如何找到每个经理下的所有员工

Oracle Sql 查询以获取经理与员工的关系

SQL查询按区域返回***经理

不允许 SQL Server 约束子查询

SQL Server CTE 和递归示例

SQL SERVER 下:1递归查询父分类下的各个子分类。 2查询每个商品分类中最贵的前两个商品SQL