使用没有任何聚合功能的PIVOT

时间:2019-04-24 09:31:58

标签: sql-server

我有这个表结构,每天存储员工的出勤情况。我想得到结果,以便我可以在日期下知道员工签到了多少次,如果签到,它将显示任何状态,例如IN,如果签出,则在单独的列中说OUT。

/****** Object:  Table [dbo].[Attendance]    Script Date: 4/24/2019 2:22:47 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Attendance](
    [EmpCode] [int] NULL,
    [TimeIn] [datetime] NULL,
    [TimeOut] [datetime] NULL
) ON [PRIMARY]

GO
/****** Object:  Table [dbo].[Employee]    Script Date: 4/24/2019 2:22:47 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Employee](
    [ID] [int] NOT NULL,
    [EmployeeName] [varchar](25) NULL,
    [Department] [varchar](25) NULL,
    [CenterCode] [int] NULL,
 CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[Attendance] ([EmpCode], [TimeIn], [TimeOut]) VALUES (1, CAST(N'2019-02-01 06:30:00.000' AS DateTime), NULL)
GO
INSERT [dbo].[Attendance] ([EmpCode], [TimeIn], [TimeOut]) VALUES (1, NULL, CAST(N'2019-02-01 18:22:00.000' AS DateTime))
GO
INSERT [dbo].[Attendance] ([EmpCode], [TimeIn], [TimeOut]) VALUES (1, CAST(N'2019-02-02 07:21:00.000' AS DateTime), NULL)
GO
INSERT [dbo].[Attendance] ([EmpCode], [TimeIn], [TimeOut]) VALUES (1, NULL, CAST(N'2019-02-02 19:54:00.000' AS DateTime))
GO
INSERT [dbo].[Employee] ([ID], [EmployeeName], [Department], [CenterCode]) VALUES (1, N'Asim', N'Information Tech', 4)
GO
INSERT [dbo].[Employee] ([ID], [EmployeeName], [Department], [CenterCode]) VALUES (2, N'Ali', N'Information Tech', 2)
GO
INSERT [dbo].[Employee] ([ID], [EmployeeName], [Department], [CenterCode]) VALUES (3, N'Isaac', N'Information Tech', 3)
GO
INSERT [dbo].[Employee] ([ID], [EmployeeName], [Department], [CenterCode]) VALUES (4, N'Swagger', N'Information Tech', 4)
GO
INSERT [dbo].[Employee] ([ID], [EmployeeName], [Department], [CenterCode]) VALUES (5, N'Nadine', N'Information Tech', 2)
GO
INSERT [dbo].[Employee] ([ID], [EmployeeName], [Department], [CenterCode]) VALUES (6, N'Julie', N'Information Tech', 4)
GO
INSERT [dbo].[Employee] ([ID], [EmployeeName], [Department], [CenterCode]) VALUES (7, N'Meachum', N'Information Tech', 3)
GO
INSERT [dbo].[Employee] ([ID], [EmployeeName], [Department], [CenterCode]) VALUES (8, N'Bob Lee', N'Information Tech', 4)
GO
ALTER TABLE [dbo].[Attendance]  WITH CHECK ADD  CONSTRAINT [FK_Attendance_Employee] FOREIGN KEY([EmpCode])
REFERENCES [dbo].[Employee] ([ID])
GO
ALTER TABLE [dbo].[Attendance] CHECK CONSTRAINT [FK_Attendance_Employee]
GO

现在我已经写了一个查询,但是由于我不确定如何在没有聚合函数的情况下使用PIVOT函数,因此我使用的是MIN(),这就是为什么它只给我一天的第一次超时/超时的原因。

以下是查询:

SELECT * FROM (

    SELECT E.ID, E.EmployeeName, T.DateToCheck, COALESCE(A.val, 'Absent') val
    FROM Employee E
    CROSS JOIN (
        SELECT CAST(DATEADD(DAY, number, '2019-02-01') AS DATE)
        FROM master..spt_values
        WHERE type = 'P'
        AND DATEADD(DAY, number, '2019-02-01') <= '2019-02-28') T(DateToCheck)
    LEFT JOIN (SELECT CAST(CAST(COALESCE(TimeIn, TimeOut) AS TIME) AS VARCHAR) val, CAST(COALESCE(TimeIn, TimeOut) AS DATE) AttendanceDateTime, EmpCode FROM Attendance) A ON CAST(A.AttendanceDateTime AS DATE) = T.DateToCheck AND A.EmpCode = E.ID
    ) T

PIVOT (MIN(val) FOR DateToCheck IN ([2019-02-01],[2019-02-02],[2019-02-03],[2019-02-04],[2019-02-05],[2019-02-06],[2019-02-07],[2019-02-08],[2019-02-09],[2019-02-10],[2019-02-11],[2019-02-12],[2019-02-13],[2019-02-14],[2019-02-15],[2019-02-16],[2019-02-17],[2019-02-18],[2019-02-19],[2019-02-20],[2019-02-21],[2019-02-22],[2019-02-23],[2019-02-24],[2019-02-25],[2019-02-26],[2019-02-27],[2019-02-28])) P;

预期的输出结果是这样的

EmployeeName   Status   2019-02-01   2019-02-02
Asim           IN       06:30        07:21
Asim           OUT      11:39        19:54
Asim           IN       13:06        NULL
Asim           OUT      18:22        NULL

0 个答案:

没有答案