使用 SQL 查询合并三个表并获得一个输出
Merge Three Tables and get one output using SQL query
我有以下候选人 table 详细信息
Table_TraineeInfo
TraineeID BatchId Name Mobile
--------------------------------------------------
243 45 demo201 9888562341
244 45 demo202 9888562342
246 45 demo204 9888562344
这是我的上述候选人的批次详细信息,在两个常见 tables
中都有参考 ID 45
Table_Batch_Lookup
BatchId BatchStartDate BatchEndDate
------------------------------------------------------------------------
45 2019-11-27 00:00:00.000 2019-11-29 23:59:59.000
下面是我的Trainee出勤记录table Table_TraineeInfo和Table_Attendance_Log的共同点是TraineeID
Table_Attendance_Log
TraineeID BatchId Attendance Date
------------------------------------------------------------
243 45 Present 2019-11-27 17:55:56.513
243 45 Present 2019-11-28 17:58:06.220
243 45 Absent 2019-11-29 18:00:56.820
244 45 Present 2019-11-29 18:05:03.930
246 45 Absent 2019-11-28 18:09:08.567
246 45 Present 2019-11-29 18:09:08.567
我想要像下面这样的输出合并三个 tables 并使用 SQL 查询或可能的方式得到一个输出作为批量候选人出勤报告。
TraineeID BatchId Name Mobile 2019-11-27 2019-11-28 2019-11-29 Score
-----------------------------------------------------------------------------------------------------------------------------
243 45 demo201 9888562341 Present Present Absent 3/2
244 45 demo202 9888562342 No Record No Record Present 3/1
246 45 demo204 9888562344 No Record Absent Present 3/1
我将解释上面的输出,前四列将使用 Table_TraineeInfo 填充,接下来的数据将基于 Table_Batch_Lookup 的 BatchStartDate 和 BatchEndDate 填充,并且
出席和缺席将根据Table_Attendance_Log attendacne 列表中没有可用数据然后不填写记录,最后得分出席将1 值和3 天。
Impossible to create one query with different column count and column
names.
解决方法是为 dynamic SQL query
形成创建一个脚本。或者我可以使用名为 [day1],[day2],...,[dayN]...
的列编写查询
如果 BatchEndDate and BatchStartDate
之间始终相同 day's count
。
我不确定它的解决方案有多接近,但您可能需要动态枢轴。
请尝试以下:
CREATE TABLE Table_TraineeInfo (TraineeID int,BatchId int,Name varchar(max),Mobile varchar(10))
INSERT INTO Table_TraineeInfo VALUES(243, 45 , 'demo201' , '9888562341')
INSERT INTO Table_TraineeInfo VALUES(244, 45 , 'demo202' , '9888562342')
INSERT INTO Table_TraineeInfo VALUES(246, 45 , 'demo204' , '9888562344')
CREATE TABLE Table_Attendance_Log (TraineeID INT, BatchId INT, Attendance VARCHAR(10) , l_date DATETIME)
INSERT INTO Table_Attendance_Log VALUES (243, 45 , 'Present' ,'2019-11-27 17:55:56.513')
INSERT INTO Table_Attendance_Log VALUES (243, 45 , 'Present' ,'2019-11-28 17:58:06.220')
INSERT INTO Table_Attendance_Log VALUES (243, 45 , 'Absent' ,'2019-11-29 18:00:56.820')
INSERT INTO Table_Attendance_Log VALUES (244, 45 , 'Present' ,'2019-11-29 18:05:03.930')
INSERT INTO Table_Attendance_Log VALUES (246, 45 , 'Absent' ,'2019-11-28 18:09:08.567')
INSERT INTO Table_Attendance_Log VALUES (246, 45 , 'Present' ,'2019-11-29 18:09:08.567')
CREATE TABLE Table_Batch_Lookup (BatchId int , BatchStartDate DATETIME , BatchEndDate DATETIME)
INSERT INTO Table_Batch_Lookup VALUES( 45 , '2019-11-27 00:00:00.000', '2019-11-29 23:59:59.000')
日期CTE
Declare @cols NVARCHAR(Max)='';
;With log_date AS (
SELECT BatchStartDate as l_date FROM Table_Batch_Lookup
UNION ALL
SELECT DATEADD(dd, 1, l_date) FROM log_date AS ld , Table_Batch_Lookup AS tb WHERE ld.l_date<DATEADD(dd, -1, tb.BatchEndDate)
)
SELECT @cols = COALESCE (@cols + ',[' + CONVERT(NVARCHAR,CONVERT(VARCHAR(10), l_Date, 111), 106) + ']','[' + CONVERT(NVARCHAR, l_Date, 106) + ']') FROM (SELECT DISTINCT CONVERT(VARCHAR(10), l_Date, 111) AS l_date FROM log_date) PV;
动态Pivot
Declare @totalScore INT =len(@cols) - len(replace(@cols, ',', ''))
CREATE TABLE #scoreTable (TraineeID int,Score Varchar(max))
INSERT INTO #scoreTable SELECT TraineeID,(CAST (@totalScore AS VARCHAR(10)) +'/'+CAST (SUM(CASE WHEN Attendance='Present' THEN 1 ELSE 0 END) AS VARCHAR(10)))AS Score from Table_Attendance_Log GROUP BY TraineeID;
--SELECT * from #scoreTable
DECLARE @query NVARCHAR(MAX);
SET @query = 'SELECT t_info.TraineeID,t_batch.BatchId,t_info.Name,t_info.Mobile'+@cols+' ,s.Score FROM Table_TraineeInfo AS t_info JOIN
(SELECT * FROM
(
SELECT TraineeID,BatchId,Attendance,CONVERT(VARCHAR(10), l_Date, 111) AS l_date FROM Table_Attendance_Log
) x
PIVOT
(
MAX(Attendance)
FOR l_Date IN (' + right(@cols, len(@cols)-1)+ ')
) p ) AS f_pv ON t_info.TraineeID=f_pv.TraineeID
JOIN Table_Batch_Lookup as t_batch ON t_batch.BatchId=t_info.BatchId
JOIN #scoreTable AS s ON t_info.TraineeID=s.TraineeID
WHERE t_batch.BatchId=45;
' ;
EXEC SP_EXECUTESQL @query;
输出:
TraineeID BatchId Name Mobile 2019/11/27 2019/11/28 2019/11/29 Score
243 45 demo201 9888562341 Present Present Absent 3/2
244 45 demo202 9888562342 Present 3/1
246 45 demo204 9888562344 Absent Present 3/1
我有以下候选人 table 详细信息
Table_TraineeInfo
TraineeID BatchId Name Mobile
--------------------------------------------------
243 45 demo201 9888562341
244 45 demo202 9888562342
246 45 demo204 9888562344
这是我的上述候选人的批次详细信息,在两个常见 tables
中都有参考 ID 45Table_Batch_Lookup
BatchId BatchStartDate BatchEndDate
------------------------------------------------------------------------
45 2019-11-27 00:00:00.000 2019-11-29 23:59:59.000
下面是我的Trainee出勤记录table Table_TraineeInfo和Table_Attendance_Log的共同点是TraineeID
Table_Attendance_Log
TraineeID BatchId Attendance Date
------------------------------------------------------------
243 45 Present 2019-11-27 17:55:56.513
243 45 Present 2019-11-28 17:58:06.220
243 45 Absent 2019-11-29 18:00:56.820
244 45 Present 2019-11-29 18:05:03.930
246 45 Absent 2019-11-28 18:09:08.567
246 45 Present 2019-11-29 18:09:08.567
我想要像下面这样的输出合并三个 tables 并使用 SQL 查询或可能的方式得到一个输出作为批量候选人出勤报告。
TraineeID BatchId Name Mobile 2019-11-27 2019-11-28 2019-11-29 Score
-----------------------------------------------------------------------------------------------------------------------------
243 45 demo201 9888562341 Present Present Absent 3/2
244 45 demo202 9888562342 No Record No Record Present 3/1
246 45 demo204 9888562344 No Record Absent Present 3/1
我将解释上面的输出,前四列将使用 Table_TraineeInfo 填充,接下来的数据将基于 Table_Batch_Lookup 的 BatchStartDate 和 BatchEndDate 填充,并且 出席和缺席将根据Table_Attendance_Log attendacne 列表中没有可用数据然后不填写记录,最后得分出席将1 值和3 天。
Impossible to create one query with different column count and column names.
解决方法是为 dynamic SQL query
形成创建一个脚本。或者我可以使用名为 [day1],[day2],...,[dayN]...
如果 BatchEndDate and BatchStartDate
之间始终相同 day's count
。
我不确定它的解决方案有多接近,但您可能需要动态枢轴。
请尝试以下:
CREATE TABLE Table_TraineeInfo (TraineeID int,BatchId int,Name varchar(max),Mobile varchar(10))
INSERT INTO Table_TraineeInfo VALUES(243, 45 , 'demo201' , '9888562341')
INSERT INTO Table_TraineeInfo VALUES(244, 45 , 'demo202' , '9888562342')
INSERT INTO Table_TraineeInfo VALUES(246, 45 , 'demo204' , '9888562344')
CREATE TABLE Table_Attendance_Log (TraineeID INT, BatchId INT, Attendance VARCHAR(10) , l_date DATETIME)
INSERT INTO Table_Attendance_Log VALUES (243, 45 , 'Present' ,'2019-11-27 17:55:56.513')
INSERT INTO Table_Attendance_Log VALUES (243, 45 , 'Present' ,'2019-11-28 17:58:06.220')
INSERT INTO Table_Attendance_Log VALUES (243, 45 , 'Absent' ,'2019-11-29 18:00:56.820')
INSERT INTO Table_Attendance_Log VALUES (244, 45 , 'Present' ,'2019-11-29 18:05:03.930')
INSERT INTO Table_Attendance_Log VALUES (246, 45 , 'Absent' ,'2019-11-28 18:09:08.567')
INSERT INTO Table_Attendance_Log VALUES (246, 45 , 'Present' ,'2019-11-29 18:09:08.567')
CREATE TABLE Table_Batch_Lookup (BatchId int , BatchStartDate DATETIME , BatchEndDate DATETIME)
INSERT INTO Table_Batch_Lookup VALUES( 45 , '2019-11-27 00:00:00.000', '2019-11-29 23:59:59.000')
日期CTE
Declare @cols NVARCHAR(Max)='';
;With log_date AS (
SELECT BatchStartDate as l_date FROM Table_Batch_Lookup
UNION ALL
SELECT DATEADD(dd, 1, l_date) FROM log_date AS ld , Table_Batch_Lookup AS tb WHERE ld.l_date<DATEADD(dd, -1, tb.BatchEndDate)
)
SELECT @cols = COALESCE (@cols + ',[' + CONVERT(NVARCHAR,CONVERT(VARCHAR(10), l_Date, 111), 106) + ']','[' + CONVERT(NVARCHAR, l_Date, 106) + ']') FROM (SELECT DISTINCT CONVERT(VARCHAR(10), l_Date, 111) AS l_date FROM log_date) PV;
动态Pivot
Declare @totalScore INT =len(@cols) - len(replace(@cols, ',', ''))
CREATE TABLE #scoreTable (TraineeID int,Score Varchar(max))
INSERT INTO #scoreTable SELECT TraineeID,(CAST (@totalScore AS VARCHAR(10)) +'/'+CAST (SUM(CASE WHEN Attendance='Present' THEN 1 ELSE 0 END) AS VARCHAR(10)))AS Score from Table_Attendance_Log GROUP BY TraineeID;
--SELECT * from #scoreTable
DECLARE @query NVARCHAR(MAX);
SET @query = 'SELECT t_info.TraineeID,t_batch.BatchId,t_info.Name,t_info.Mobile'+@cols+' ,s.Score FROM Table_TraineeInfo AS t_info JOIN
(SELECT * FROM
(
SELECT TraineeID,BatchId,Attendance,CONVERT(VARCHAR(10), l_Date, 111) AS l_date FROM Table_Attendance_Log
) x
PIVOT
(
MAX(Attendance)
FOR l_Date IN (' + right(@cols, len(@cols)-1)+ ')
) p ) AS f_pv ON t_info.TraineeID=f_pv.TraineeID
JOIN Table_Batch_Lookup as t_batch ON t_batch.BatchId=t_info.BatchId
JOIN #scoreTable AS s ON t_info.TraineeID=s.TraineeID
WHERE t_batch.BatchId=45;
' ;
EXEC SP_EXECUTESQL @query;
输出:
TraineeID BatchId Name Mobile 2019/11/27 2019/11/28 2019/11/29 Score
243 45 demo201 9888562341 Present Present Absent 3/2
244 45 demo202 9888562342 Present 3/1
246 45 demo204 9888562344 Absent Present 3/1