OK, as i wrote, i try to show how to do the same using two different methods.
My database name:
A_TEST
My data in the table
Checkings
looks like:
UserID | chDateTime | CheckingType |
---|
888 | 2011-01-01 08:30:00.000 | 1 |
889 | 2011-01-01 08:32:00.000 | 1 |
885 | 2011-01-01 08:35:00.000 | 1 |
888 | 2011-01-01 16:30:00.000 | 2 |
889 | 2011-01-01 00:42:00.000 | 2 |
885 | 2011-01-01 00:55:00.000 | 2 |
888 | 2011-01-02 08:30:00.000 | 1 |
889 | 2011-01-02 08:32:00.000 | 1 |
885 | 2011-01-02 08:35:00.000 | 1 |
888 | 2011-01-02 16:30:00.000 | 2 |
889 | 2011-01-02 00:42:00.000 | 2 |
885 | 2011-01-02 00:55:00.000 | 2 |
--- METHOD 1: JOIN ---
USE [A_TEST];
DECLARE @sqry NVARCHAR(2000)
DECLARE @fqry NVARCHAR(2000)
DECLARE @mqry NVARCHAR(2000)
SET @sqry = 'SELECT UserID, CONVERT(DATETIME,CONVERT(NVARCHAR, YEAR([chDateTime])) + ''-'' + CONVERT(NVARCHAR, MONTH([chDateTime])) + ''-'' + CONVERT(NVARCHAR, DAY([chDateTime]))) AS [chDate], RIGHT([chDateTime],8) AS CheckInTime ' +
'FROM [dbo].[Checkings]' +
'WHERE CheckingType = 1'
SET @fqry = 'SELECT UserID, CONVERT(DATETIME,CONVERT(NVARCHAR, YEAR([chDateTime])) + ''-'' + CONVERT(NVARCHAR, MONTH([chDateTime])) + ''-'' + CONVERT(NVARCHAR, DAY([chDateTime]))) AS [chDate], RIGHT([chDateTime],8) AS CheckOutTime ' +
'FROM [dbo].[Checkings]' +
'WHERE CheckingType = 2'
SET @mqry = 'SELECT tblA.[UserID], tblA.[chDate], tblA.[CheckInTime], tblB.[CheckOutTime] ' +
'FROM (' + @sqry + ') AS tblA RIGHT OUTER JOIN (' + @fqry + ') AS tblB ON tblA.[UserID] = tblB.[UserID] ' +
'WHERE tblA.chDate = tblB.chDate ' +
'ORDER BY tblA.chDate'
EXECUTE(@mqry)
--- METHOD 2: PIVOT ---
USE [A_TEST];
DECLARE @sqry NVARCHAR(2000)
DECLARE @mqry NVARCHAR(2000)
DECLARE @cols NVARCHAR(2000)
SET @cols = STUFF((SELECT DISTINCT '],[' + CONVERT(NVARCHAR, [CheckingType])
FROM [dbo].[Checkings]
ORDER BY '],[' + CONVERT(NVARCHAR, [CheckingType])
FOR XML PATH('')), 1, 2, '') + ']'
SET @sqry = 'SELECT [UserID], CONVERT(DATETIME,CONVERT(NVARCHAR, YEAR([chDateTime])) + ''-'' + CONVERT(NVARCHAR, MONTH([chDateTime])) + ''-'' + CONVERT(NVARCHAR, DAY([chDateTime]))) AS [chDate], RIGHT([chDateTime],8) AS chTime, CheckingType ' +
'FROM [dbo].[Checkings]'
SET @mqry = 'SELECT [UserId], [chDate], ' + @cols + ' ' +
'FROM (' + @sqry + ') AS DT ' +
'PIVOT (MAX(DT.[chTime]) FOR DT.[CheckingType] IN ( ' + @cols + ' )) AS PT ' +
'ORDER BY PT.[chDate]'
EXECUTE(@mqry)
--- RESULTS: ---
results are the same in both examples, differ only column headers
--- JOIN ---
UserID | chDate | CheckInTime | CheckOutTime |
---|
885 | 2011-01-01 00:00:00.000 | 8:35AM | 4:55PM |
888 | 2011-01-01 00:00:00.000 | 8:30AM | 4:35PM |
889 | 2011-01-01 00:00:00.000 | 8:32AM | 4:42PM |
885 | 2011-01-02 00:00:00.000 | 8:35AM | 4:55PM |
888 | 2011-01-02 00:00:00.000 | 8:30AM | 4:30PM |
889 | 2011-01-03 00:00:00.000 | 8:32AM | 4:42PM |
--- PIVOT ---
UserID | chDate | 1 | 2 |
---|
885 | 2011-01-01 00:00:00.000 | 8:35AM | 4:55PM |
888 | 2011-01-01 00:00:00.000 | 8:30AM | 4:35PM |
889 | 2011-01-01 00:00:00.000 | 8:32AM | 4:42PM |
885 | 2011-01-02 00:00:00.000 | 8:35AM | 4:55PM |
888 | 2011-01-02 00:00:00.000 | 8:30AM | 4:30PM |
889 | 2011-01-03 00:00:00.000 | 8:32AM | 4:42PM |
I don't know how to use it in Crystal Reports but i'm sure the solution will be helpful. Probably, we need to create a stored procedure (i.e.: pvtCheckings) and then use it as a source of Crystal Report (how? i don't know!):
USE [A_TEST];
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE pvtCheckings
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sqry NVARCHAR(2000)
DECLARE @mqry NVARCHAR(2000)
DECLARE @cols NVARCHAR(2000)
SET @cols = STUFF((SELECT DISTINCT '],[' + CONVERT(NVARCHAR, [CheckingType])
FROM [dbo].[Checkings]
ORDER BY '],[' + CONVERT(NVARCHAR, [CheckingType])
FOR XML PATH('')), 1, 2, '') + ']'
SET @sqry = 'SELECT [UserID], CONVERT(DATETIME,CONVERT(NVARCHAR, YEAR([chDateTime])) + ''-'' + CONVERT(NVARCHAR, MONTH([chDateTime])) + ''-'' + CONVERT(NVARCHAR, DAY([chDateTime]))) AS [chDate], RIGHT([chDateTime],8) AS chTime, CheckingType ' +
'FROM [dbo].[Checkings]'
SET @mqry = 'SELECT [UserId], [chDate], ' + @cols + ' ' +
'FROM (' + @sqry + ') AS DT ' +
'PIVOT (MAX(DT.[chTime]) FOR DT.[CheckingType] IN ( ' + @cols + ' )) AS PT ' +
'ORDER BY PT.[chDate]'
EXECUTE(@mqry)
END
GO
USAGE (in MS SQL Server Management Studio):
DECLARE @RC int
EXECUTE @RC = [A_TEST].[dbo].[pvtCheckings]
In both examples we need to extract part of date and time, becouse DateTime field includes date and time. Until time part is differ we can't equal results.