SQL Server – Query to split time by count (overlapping offices)
我正在寻找一些关于我应该采取的查询方法的建议。我有一张表 (EMP),其中存储了今年的员工详细信息和工作时间(每周 40 小时)。另外 2 个表存储员工所属的主要和次要办公室。由于员工可以在办公室之间移动,因此这些都与日期一起存储。
我希望返回员工在办公室期间的工作小时数。如果员工的主要办公室与次要办公室重叠,则小时数应仅按重叠期间的重叠办公室数量进行划分。
我在下面附上了示例 DDL。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
— Employee Table with hours for year 2014
CREATE TABLE [dbo].[EMP]( GO — Employees and their primary offices CREATE TABLE [dbo].[OFFICEPRIMARY]( GO SET ANSI_PADDING OFF ALTER TABLE [dbo].[OFFICEPRIMARY] WITH CHECK ADD CONSTRAINT [FK_OFFICEPRIMARY_FK1] FOREIGN KEY([OFFICEPRIMARY_EMP_ID]) ALTER TABLE [dbo].[OFFICEPRIMARY] CHECK CONSTRAINT [FK_OFFICEPRIMARY_FK1] — Employees and their secondary offices CREATE TABLE [dbo].[OFFICESECONDARY]( GO SET ANSI_PADDING OFF ALTER TABLE [dbo].[OFFICESECONDARY] WITH CHECK ADD CONSTRAINT [FK_OFFICESECONDARY_FK1] FOREIGN KEY([OFFICESECONDARY_EMP_ID]) ALTER TABLE [dbo].[OFFICESECONDARY] CHECK CONSTRAINT [FK_OFFICESECONDARY_FK1] — Insert sample data INSERT INTO EMP (EMP_ID, EMP_NAME, EMP_FYHOURS) INSERT INTO EMP (EMP_ID, EMP_NAME, EMP_FYHOURS) GO INSERT INTO OFFICEPRIMARY (OFFICEPRIMARY_ID, OFFICEPRIMARY_NAME, OFFICEPRIMARY_EMP_ID, OFFICEPRIMARY_START, OFFICEPRIMARY_END) INSERT INTO OFFICEPRIMARY (OFFICEPRIMARY_ID, OFFICEPRIMARY_NAME, OFFICEPRIMARY_EMP_ID, OFFICEPRIMARY_START, OFFICEPRIMARY_END) INSERT INTO OFFICEPRIMARY (OFFICEPRIMARY_ID, OFFICEPRIMARY_NAME, OFFICEPRIMARY_EMP_ID, OFFICEPRIMARY_START, OFFICEPRIMARY_END) INSERT INTO OFFICEPRIMARY (OFFICEPRIMARY_ID, OFFICEPRIMARY_NAME, OFFICEPRIMARY_EMP_ID, OFFICEPRIMARY_START, OFFICEPRIMARY_END) INSERT INTO OFFICEPRIMARY (OFFICEPRIMARY_ID, OFFICEPRIMARY_NAME, OFFICEPRIMARY_EMP_ID, OFFICEPRIMARY_START, OFFICEPRIMARY_END) INSERT INTO OFFICEPRIMARY (OFFICEPRIMARY_ID, OFFICEPRIMARY_NAME, OFFICEPRIMARY_EMP_ID, OFFICEPRIMARY_START, OFFICEPRIMARY_END) GO INSERT INTO OFFICESECONDARY (OFFICESECONDARY_ID, OFFICESECONDARY_NAME, OFFICESECONDARY_EMP_ID, OFFICESECONDARY_START, OFFICESECONDARY_END) INSERT INTO OFFICESECONDARY (OFFICESECONDARY_ID, OFFICESECONDARY_NAME, OFFICESECONDARY_EMP_ID, OFFICESECONDARY_START, OFFICESECONDARY_END) INSERT INTO OFFICESECONDARY (OFFICESECONDARY_ID, OFFICESECONDARY_NAME, OFFICESECONDARY_EMP_ID, OFFICESECONDARY_START, OFFICESECONDARY_END) INSERT INTO OFFICESECONDARY (OFFICESECONDARY_ID, OFFICESECONDARY_NAME, OFFICESECONDARY_EMP_ID, OFFICESECONDARY_START, OFFICESECONDARY_END) INSERT INTO OFFICESECONDARY (OFFICESECONDARY_ID, OFFICESECONDARY_NAME, OFFICESECONDARY_EMP_ID, OFFICESECONDARY_START, OFFICESECONDARY_END) INSERT INTO OFFICESECONDARY (OFFICESECONDARY_ID, OFFICESECONDARY_NAME, OFFICESECONDARY_EMP_ID, OFFICESECONDARY_START, OFFICESECONDARY_END) INSERT INTO OFFICESECONDARY (OFFICESECONDARY_ID, OFFICESECONDARY_NAME, OFFICESECONDARY_EMP_ID, OFFICESECONDARY_START, OFFICESECONDARY_END) GO |
感谢您的指点。我调整了您的查询,使其呈现主要和次要办公室的联合。
剩下的就是计算办公室之间重叠时段的工作时间。例如,
约翰·史密斯,纽约,2014 年 1 月 4 日,2014 年 10 月 8 日
约翰·史密斯,伦敦,2014 年 1 月 8 日,2014 年 12 月 31 日
对于 2014 年 1 月 8 日至 2014 年 8 月 10 日这两个办公室之间的重叠时间段,我预计工作时间将平均分配。如果有 3 个重叠的办公室,那么它将被分成 3 路。
1
2 3 4 5 6 7 8 |
SELECT ‘Primary’ AS Office, e.EMP_NAME, op.OFFICEPRIMARY_NAME, op.OFFICEPRIMARY_START, op.OFFICEPRIMARY_END, datediff(wk,OFFICEPRIMARY_START,OFFICEPRIMARY_END) * 40 AS HoursWorkedPrimary
FROM EMP e INNER JOIN OFFICEPRIMARY op ON op.OFFICEPRIMARY_EMP_ID = e.EMP_ID UNION ALL SELECT ‘Secondary’ AS Office, e.EMP_NAME, os.OFFICESECONDARY_NAME, os.OFFICESECONDARY_START, os.OFFICESECONDARY_END, datediff(wk,OFFICESECONDARY_START,OFFICESECONDARY_END) * 40 AS HoursWorkedSecondary FROM EMP e INNER JOIN OFFICESECONDARY os ON os.OFFICESECONDARY_EMP_ID = e.EMP_ID ORDER BY e.EMP_NAME |
如果我理解正确,您希望看到的最终结果是每个员工和办公室的总工作小时数?
我想出了这个:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
— generate date table
DECLARE @MinDate datetime, @MaxDate datetime SET @MinDate = (SELECT MIN(d) FROM (SELECT d = OFFICEPRIMARY_START FROM dbo.OFFICEPRIMARY UNION SELECT OFFICESECONDARY_START FROM dbo.OFFICESECONDARY) a) SET @MaxDate = (SELECT MAX(d) FROM (SELECT d = OFFICEPRIMARY_END FROM dbo.OFFICEPRIMARY UNION SELECT OFFICESECONDARY_END FROM dbo.OFFICESECONDARY) a) SELECT
;WITH CTE AS UNION SELECT INNER JOIN SELECT |
我首先生成一个临时表,其中包含最小日期和最大日期之间的日期。
然后我合并两个办公室表(为什么你有 2 个表?),我得到一个 CTE,它返回关于员工、日期、办公室和在这个办公室工作的小时数的数据(8 除以员工所在办公室的数量)这一天上班)。
然后我将这些数据相加,得到按员工和办公室分组的小时总和。
也许有一个更简单的解决方案。这是我想到的第一个解决方案。
下面的链接应该可以帮助您指出正确的方向,以确定日期如何重叠。
计算日期范围内可能重叠的排除天数
这应该会给你一个良好的开端:
1
2 3 4 5 6 7 8 |
SELECT datediff(wk,OFFICEPRIMARY_START,OFFICEPRIMARY_END) * 40 AS HoursWorkedPrimary
,datediff(wk,OFFICESECONDARY_START,OFFICESECONDARY_END) * 40 AS HoursWorkedSecondary ,EMP_NAME ,OFFICEPRIMARY_NAME,OFFICEPRIMARY_START,OFFICEPRIMARY_END ,OFFICESECONDARY_NAME,OFFICESECONDARY_START,OFFICESECONDARY_END FROM [EMP] INNER JOIN OFFICEPRIMARY AS op ON op.OFFICEPRIMARY_EMP_ID = EMP.EMP_ID INNER JOIN OFFICESECONDARY AS os ON os.OFFICESECONDARY_EMP_ID = EMP.EMP_ID |
- 感谢您的指点。我调整了您的查询,使其呈现主要和次要办公室的联合。
来源:https://www.codenong.com/24649278/