作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我被要求将大型 Excel 日历转换为 SQL 表结构,以便我们可以将其功能包含在我们的内部应用程序中。为了更容易解释,我做了一个虚拟的例子:
这只是一个星期,但它会在一年中的所有星期中一直持续到最右边。你可以明白为什么这是大量的体力劳动。
这个日历告诉我们:
PlanningDay
是最重要的。
Employee
, 具有日期值并用 bool 值表示 AM 或 PM(AM 为真或假)。一个
PlanningDay
总是链接到一个
PlanningDayDetail
.
重要的是要知道,当在表 PlanningDay
中找不到条目时,应该显示默认的 OF(办公室),除非是周末)。 仅注册“异常(exception)”。
PlanningDayType
(如 Absent),以及更具体的名称和缩写,如 Holiday 和 HOL。
Employee
返回 1 行, 2 列(AM 和 PM)包含
DisplayName
链接到
PlanningDay
的详细信息(如果在那个日期 AM/PM 注册了一个),用于介于开始和结束日期参数之间的每个日期。基本上和Excel完全一样。
CREATE TABLE [Mrd].[Employee]
(
[Id] INT IDENTITY(1,1) CONSTRAINT [PK_Mrd_Employee_Id] PRIMARY KEY,
[FirstName] NVARCHAR(100) NOT NULL,
[LastName] NVARCHAR(100) NULL,
)
CREATE TABLE [Mrd].[PlanningDay]
(
[Id] INT IDENTITY(1,1) CONSTRAINT [PK_Mrd_PlanningDay_Id] PRIMARY KEY,
[EmployeeId] INT NOT NULL,
[Date] DATE NOT NULL,
[AM] BIT NOT NULL,
[PlanningDayDealId] INT NOT NULL,
CONSTRAINT [FK_Mrd_PlanningDay_PlanningDayDealId_Mrd_PlanningDayDetail_Id]
FOREIGN KEY ([PlanningDayDealId])
REFERENCES [Mrd].[PlanningDayDetail] ([Id]),
CONSTRAINT [FK_Mrd_PlanningDay_EmployeeId_Mrd_Employee_Id]
FOREIGN KEY ([EmployeeId])
REFERENCES [Mrd].[Employee] ([Id])
)
CREATE TABLE [Mrd].[PlanningDayDetail]
(
[Id] INT IDENTITY(1,1) CONSTRAINT [PK_Mrd_PlanningDayDetail_Id] PRIMARY KEY,
[PlanningDayTypeId] INT NOT NULL,
[Name] NVARCHAR(255) NOT NULL,
[DisplayName] NVARCHAR(3) NOT NULL,
CONSTRAINT [FK_Mrd_PlanningDayDetail_PlanningDayTypeId_Mrd_PlanningDayType_Id]
FOREIGN KEY ([PlanningDayTypeId])
REFERENCES [Mrd].[PlanningDayType] ([Id])
)
CREATE TABLE [Mrd].[PlanningDayType]
(
[Id] INT IDENTITY(1,1) CONSTRAINT [PK_Mrd_PlanningDayType_Id] PRIMARY KEY,
[Name] NVARCHAR(255) NOT NULL,
[ReportColor] NVARCHAR(10) NOT NULL
)
INSERT INTO [Mrd].[Employee] ([FirstName],[LastName])
VALUES
('Sandra','Cooper'),
('James','Adams'),
('Martha','Reid');
INSERT INTO [Mrd].[PlanningDayType] ([Name],[ReportColor])
VALUES
('Absent','#8b4789'),
('Consultancy','#c7c700');
INSERT INTO [Mrd].[PlanningDayDetail] ([PlanningDayTypeId],[Name],[DisplayName])
VALUES
(1,'New Year','HOL'),
(2,'Customer A','C-A');
INSERT INTO [Mrd].[PlanningDay] ([EmployeeId],[Date],[AM],[PlanningDayDealId])
VALUES
(1,'2018-01-01',1,1),
(1,'2018-01-01',0,1),
(2,'2018-01-01',1,1),
(2,'2018-01-01',0,1),
(3,'2018-01-01',1,1),
(3,'2018-01-01',0,1),
(2,'2018-01-03',1,2),
(2,'2018-01-03',0,2),
(2,'2018-01-04',1,2),
(2,'2018-01-04',0,2),
(2,'2018-01-05',1,2);
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| Employee | 2018-01-01 AM | 2018-01-01 PM | 2018-01-02 AM | 2018-01-02 PM | 2018-01-03 AM | 2018-01-03 PM |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| Sandra Cooper | HOL | HOL | OF | OF | OF | OF |
| James Adams | HOL | HOL | OF | OF | C-A | C-A |
| Martha Reid | HOL | HOL | OF | OF | OF | OF |
+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
DECLARE @StartDate DATE = '2018-01-01';
DECLARE @EndDate DATE = '2018-01-31';
WITH AllDays AS
(SELECT @StartDate AS [Day]
UNION ALL
SELECT DATEADD(DAY, 1, [Day])
FROM AllDays
WHERE [Day] < @EndDate)
SELECT ad.[Day] AS 'Date', pd.[AM], pdd.[DisplayName], e.[FirstName] + ' ' + e.[LastName] AS 'Employee'
FROM AllDays ad
LEFT JOIN [Mrd].[PlanningDay] pd
ON ad.[Day] = pd.[Date]
LEFT JOIN [Mrd].[PlanningDayDetail] pdd
ON pd.[PlanningDayDealId] = pdd.[Id]
LEFT JOIN [Mrd].[PlanningDayType] pdt
ON pdd.[PlanningDayTypeId] = pdt.[Id]
LEFT JOIN [Mrd].[Employee] e
ON pd.[EmployeeId] = e.[Id]
OPTION (MAXRECURSION 0);
+------------+------+-------------+---------------+
| Date | AM | DisplayName | Employee |
+------------+------+-------------+---------------+
| 2018-01-01 | 1 | HOL | Sandra Cooper |
| 2018-01-01 | 0 | HOL | Sandra Cooper |
| 2018-01-01 | 1 | HOL | James Adams |
| 2018-01-01 | 0 | HOL | James Adams |
| 2018-01-01 | 1 | HOL | Martha Reid |
| 2018-01-01 | 0 | HOL | Martha Reid |
| 2018-01-02 | NULL | NULL | NULL |
| 2018-01-03 | 1 | C-A | James Adams |
| 2018-01-03 | 0 | C-A | James Adams |
| 2018-01-04 | 1 | C-A | James Adams |
| 2018-01-04 | 0 | C-A | James Adams |
| 2018-01-05 | 1 | C-A | James Adams |
| 2018-01-06 | NULL | NULL | NULL |
| 2018-01-07 | NULL | NULL | NULL |
+------------+------+-------------+---------------+
PlanningDays
每人注册一次
Employee
.我首先要实现的是这个(对不起,列表太长):
+------------+----+-------------+---------------+
| Date | AM | DisplayName | Employee |
+------------+----+-------------+---------------+
| 2018-01-01 | 1 | HOL | Sandra Cooper |
| 2018-01-01 | 0 | HOL | Sandra Cooper |
| 2018-01-01 | 1 | HOL | James Adams |
| 2018-01-01 | 0 | HOL | James Adams |
| 2018-01-01 | 1 | HOL | Martha Reid |
| 2018-01-01 | 0 | HOL | Martha Reid |
| 2018-01-02 | 1 | OF | Sandra Cooper |
| 2018-01-02 | 0 | OF | Sandra Cooper |
| 2018-01-02 | 1 | OF | James Adams |
| 2018-01-02 | 0 | OF | James Adams |
| 2018-01-02 | 1 | OF | Martha Reid |
| 2018-01-02 | 0 | OF | Martha Reid |
| 2018-01-03 | 1 | OF | Sandra Cooper |
| 2018-01-03 | 0 | OF | Sandra Cooper |
| 2018-01-03 | 1 | C-A | James Adams |
| 2018-01-03 | 0 | C-A | James Adams |
| 2018-01-03 | 1 | OF | Martha Reid |
| 2018-01-03 | 0 | OF | Martha Reid |
| 2018-01-04 | 1 | OF | Sandra Cooper |
| 2018-01-04 | 0 | OF | Sandra Cooper |
| 2018-01-04 | 1 | C-A | James Adams |
| 2018-01-04 | 0 | C-A | James Adams |
| 2018-01-04 | 1 | OF | Martha Reid |
| 2018-01-04 | 0 | OF | Martha Reid |
| 2018-01-05 | 1 | OF | Sandra Cooper |
| 2018-01-05 | 0 | OF | Sandra Cooper |
| 2018-01-05 | 1 | C-A | James Adams |
| 2018-01-05 | 0 | OF | James Adams |
| 2018-01-05 | 1 | OF | Martha Reid |
| 2018-01-05 | 0 | OF | Martha Reid |
+------------+----+-------------+---------------+
PlanningDay
在客户 A 等处注册咨询...现在我知道我可以使用 COALESCE 将 NULLS 转换为默认值,但在此之前,我需要为每个没有
PlanningDay
的员工提供 NULLS。已被注册。
最佳答案
我认为你非常接近解决方案。我只是重新调整了初始连接以使用 交叉连接 这将为 Day、AM/PM 和 Employee 的每个组合生成一行。生成后,现有 左连接 s 将插入您的计划日,您可以用您在问题中指定的默认值替换 NULL。
您可以在 SQL Fiddle 中尝试此操作
DECLARE @StartDate DATE = '2018-01-01';
DECLARE @EndDate DATE = '2018-01-31';
WITH AllDays AS (
SELECT @StartDate AS [Day]
UNION ALL
SELECT
DATEADD(DAY, 1, [Day])
FROM
AllDays
WHERE
[Day] < @EndDate
)
SELECT
ad.[Day] AS 'Date'
, Period.[AM]
, pdd.[DisplayName]
, e.[FirstName] + ' ' + e.[LastName] AS 'Employee'
FROM
AllDays ad
CROSS JOIN
(SELECT CAST( 0 AS BIT ) AS [AM] UNION ALL SELECT CAST( 1 AS BIT )) AS Period
CROSS JOIN
[Employee] e
LEFT OUTER JOIN
[PlanningDay] pd ON (
pd.[Date] = ad.[Day]
AND pd.EmployeeId = e.[Id]
AND pd.[AM] = Period.[AM]
)
LEFT OUTER JOIN
[PlanningDayDetail] pdd ON (pdd.[Id] = pd.[PlanningDayDealId])
LEFT OUTER JOIN
[PlanningDayType] pdt ON (pdt.[Id] = pdd.[PlanningDayTypeId])
ORDER BY
[Date], [Employee], [AM]
关于SQL Server : Creating A Complex Calendar View For Employees,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49515878/
我是一名优秀的程序员,十分优秀!