获得员工总数最快的方式,每个部门缺席的员工总数?

时间:2016-03-02 11:32:03

标签: sql sql-server tsql sql-server-2005 rdbms

+-------+------------+
| EmpId | DepId|
+-------+------------+
|     1 | IT         |
|     2 | admin      |
|     3 | IT         |
|     4 | IT         |
|     5 | admin      |
+-------+------------+

出席率

+-------+--------+
| EmpId | Status |
+-------+--------+
|     1 | P      |
|     2 | P      |
|     3 | P      |
|     4 | A      |
|     5 | P      |
+-------+--------+

期望输出:

+-------+------------+--------------+
| DepId | TotalCount | PresentCount |
+-------+------------+--------------+
| Admin |          2 |            2 |
| IT    |          3 |            2 |
+-------+------------+--------------+

我的查询:

 SELECT DepId,
       COUNT(att.empid) total,
       sum(CASE WHEN status = 'P' THEN 1 ELSE 0 END) presetCount
FROM attendance att
INNER JOIN departments dep ON att.empid=dep.empid
GROUP BY DepId

这可以进一步优化吗?如果是的话怎么样?

2 个答案:

答案 0 :(得分:0)

IF OBJECT_ID('dbo.departments', 'U') IS NOT NULL
    DROP TABLE dbo.departments
GO
IF OBJECT_ID('dbo.attendance', 'U') IS NOT NULL
    DROP TABLE dbo.attendance
GO
CREATE TABLE dbo.departments (EmpId INT PRIMARY KEY, DepId VARCHAR(10))
GO
INSERT INTO dbo.departments
VALUES (1, 'IT'), (2, 'admin'), (3, 'IT'), (4, 'IT '), (5, 'admin')
GO
CREATE TABLE dbo.attendance (EmpId INT PRIMARY KEY, [Status] CHAR(1))
GO
INSERT INTO dbo.attendance
VALUES (1, 'P'), (2, 'P'), (3, 'P'), (4, 'A'), (5, 'P')
GO
CREATE NONCLUSTERED INDEX ix ON dbo.departments (DepId)
GO

SELECT
     DepId
   , COUNT_BIG(1) AS total
   , COUNT_BIG(att.EmpId) AS presetCount
FROM departments dep
LEFT JOIN attendance att ON att.empid = dep.EmpId AND att.[status] = 'P'
GROUP BY DepId

我的执行计划:

enter image description here

您的执行计划:

enter image description here

输出 -

DepId      total                presetCount
---------- -------------------- -------------
admin      2                    2
IT         3                    2

答案 1 :(得分:0)

因为您正在比较效果,我建议您尝试APPLY

 SELECT DepId, a.total, a.presentCount
FROM departments dep OUTER APPLY
     (SELECT COUNT(*) as total, 
             SUM(CASE WHEN status = 'P' THEN 1 ELSE 0 END) as presentCount
      FROM attendance att
      WHERE att.empid = dep.empid
     ) a;

然后,请确保您在attendance(empid, status)上有索引。

我并不是说这更快(取决于数据的大小和其他考虑因素)。但值得检查,因为它绕过外部聚合。

注意:检查小数据集的性能通常是没有意义的。执行计划和性能特征在很大程度上取决于数据的大小。