我在SQL Server中有一个表RRHH.ReportAssistence
。所有数据都从我的软件自动完成标记,该软件已完成该表。
cod_mark (int auto increment)
cod_personal (int)
cod_schedule (int)
date_mark (date)
check_in (time(0))
check_out (time(0))
查询:
select * from RRHH.ReportAssistence
cod_mark / cod_personal / cod_schedule / date_mark / check_in / check_out
--------------------------------------------------------------------------
1 / 39 / 1 /2017-03-02 / NULL / 18:10:00
2 / 39 / 1 /2017-03-05 / NULL / 18:02:00
3 / 39 / 1 /2017-03-08 / 09:20:00 / NULL
4 / 39 / 1 /2017-03-10 / NULL / 18:04:00
5 / 39 / 1 /2017-03-20 / 08:56:00 / 18:53:00
6 / 39 / 1 /2017-03-21 / 08:52:00 / 18:10:00
7 / 39 / 1 /2017-03-22 / 08:56:00 / 18:09:00
8 / 39 / 1 /2017-03-23 / NULL / 18:05:00
我需要一个存储过程,列出范围的所有日期并完成所有日期范围,如果不存在任何“date_mark”显示临时列“CONDITION”= LEFT,如果时间在“check_in”到09:15:00显示“CONDITION”= LATE,如果少到09:15:00显示“CONTIDION”= OK,如果没有check_in“CONDITION”= LEFT IN, 如果没有check_out没有问题“CONDITION”= OK
期望的结果:
SP_showMeReportAssistance (cod_personal), (startDate), (endDate)
execute SP_showMeReportAssistance 39, '01/03/2017', '23/03/2017'
cod_personal / cod_schedule / date_mark / check_in / check_out / CONDITION
39 / 1 /2017-03-01 / NULL / NULL / LEFT
39 / 1 /2017-03-02 / NULL / 18:10:00 / LEFT IN
39 / 1 /2017-03-03 / NULL / NULL / LEFT
39 / 1 /2017-03-04 / NULL / NULL / LEFT
39 / 1 /2017-03-05 / NULL / 18:02:00 / LEFT IN
39 / 1 /2017-03-06 / NULL / NULL / LEFT
39 / 1 /2017-03-07 / NULL / NULL / LEFT
39 / 1 /2017-03-08 / 09:20:00 / NULL / LATE
39 / 1 /2017-03-09 / NULL / NULL / LEFT
39 / 1 /2017-03-10 / NULL / 18:04:00 / LEFT IN
39 / 1 /2017-03-11 / NULL / NULL / LEFT
39 / 1 /2017-03-12 / NULL / NULL / LEFT
39 / 1 /2017-03-13 / NULL / NULL / LEFT
39 / 1 /2017-03-14 / NULL / NULL / LEFT
39 / 1 /2017-03-15 / NULL / NULL / LEFT
39 / 1 /2017-03-16 / NULL / NULL / LEFT
39 / 1 /2017-03-17 / NULL / NULL / LEFT
39 / 1 /2017-03-18 / NULL / NULL / LEFT
39 / 1 /2017-03-19 / NULL / NULL / LEFT
39 / 1 /2017-03-20 / 08:56:00 / 18:53:00 / OK
39 / 1 /2017-03-21 / 08:52:00 / 18:10:00 / OK
39 / 1 /2017-03-22 / 08:56:00 / 18:09:00 / OK
39 / 1 /2017-03-23 / NULL / 18:05:00 / LEFT IN
答案 0 :(得分:1)
您需要先根据传递给过程的日期生成日期列表。并LEFT JOIN
到您的实际表格。并通过向CASE
提供您的条件来获取您的条件列。
<强>架构:强>
CREATE TABLE ReportAssistence (
cod_mark INT IDENTITY
,cod_personal INT
,cod_schedule INT
,date_mark DATE
,check_in TIME(0)
,check_out TIME(0)
)
INSERT INTO ReportAssistence
SELECT 39 , 1 ,'2017-03-02' , NULL , '18:10:00'
UNION ALL
SELECT 39 , 1 ,'2017-03-05' , NULL , '18:02:00'
UNION ALL
SELECT 39 , 1 ,'2017-03-08' , '09:20:00' , NULL
UNION ALL
SELECT 39 , 1 ,'2017-03-10' , NULL , '18:04:00'
UNION ALL
SELECT 39 , 1 ,'2017-03-20' , '08:56:00' , '18:53:00'
UNION ALL
SELECT 39 , 1 ,'2017-03-21' , '08:52:00' , '18:10:00'
UNION ALL
SELECT 39 , 1 ,'2017-03-22' , '08:56:00' , '18:09:00'
UNION ALL
SELECT 39 , 1 ,'2017-03-23' , NULL , '18:05:00'
您的代码将是
DECLARE @cod_personal INT = 39
,@startDate DATE = '2017/03/01'
,@endDate DATE = '2017/03/23'
;WITH CTE AS (
SELECT DATEADD(DD, number, @startDate) AS DATES
FROM master.dbo.spt_values
WHERE TYPE = 'P'
AND DATEADD(DD, number, @startDate) <= @endDate
)
SELECT ISNULL(RA.cod_personal, @cod_personal) AS cod_personal
,cod_schedule
,DATES AS date_mark
,check_in
,check_out
,CASE
WHEN date_mark IS NULL
THEN 'LEFT'
WHEN date_mark IS NOT NULL AND check_in IS NULL
THEN 'LEFT IN'
WHEN date_mark IS NOT NULL AND check_in IS NOT NULL AND check_out IS NOT NULL
THEN 'OK'
WHEN date_mark IS NOT NULL AND check_in IS NOT NULL AND check_in > '09:15:00'
THEN 'LATE'
ELSE 'LEFT'
END AS CONDITION
FROM CTE C
LEFT JOIN ReportAssistence RA ON C.DATES = date_mark
WHERE ISNULL(RA.cod_personal, @cod_personal) = @cod_personal
结果将是
+--------------+--------------+------------+----------+-----------+-----------+
| cod_personal | cod_schedule | date_mark | check_in | check_out | CONDITION |
+--------------+--------------+------------+----------+-----------+-----------+
| 39 | NULL | 2017-03-01 | NULL | NULL | LEFT |
| 39 | 1 | 2017-03-02 | NULL | 18:10:00 | LEFT IN |
| 39 | NULL | 2017-03-03 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-04 | NULL | NULL | LEFT |
| 39 | 1 | 2017-03-05 | NULL | 18:02:00 | LEFT IN |
| 39 | NULL | 2017-03-06 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-07 | NULL | NULL | LEFT |
| 39 | 1 | 2017-03-08 | 09:20:00 | NULL | LATE |
| 39 | NULL | 2017-03-09 | NULL | NULL | LEFT |
| 39 | 1 | 2017-03-10 | NULL | 18:04:00 | LEFT IN |
| 39 | NULL | 2017-03-11 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-12 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-13 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-14 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-15 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-16 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-17 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-18 | NULL | NULL | LEFT |
| 39 | NULL | 2017-03-19 | NULL | NULL | LEFT |
| 39 | 1 | 2017-03-20 | 08:56:00 | 18:53:00 | OK |
| 39 | 1 | 2017-03-21 | 08:52:00 | 18:10:00 | OK |
| 39 | 1 | 2017-03-22 | 08:56:00 | 18:09:00 | OK |
| 39 | 1 | 2017-03-23 | NULL | 18:05:00 | LEFT IN |
+--------------+--------------+------------+----------+-----------+-----------+
答案 1 :(得分:1)
@ShakeerMirza答案是对的 - 这里是一个替代CTE,它不需要查询master数据库来构建连续日期表。 (将此作为答案而不是评论添加,因为格式很重要。)
;with cod (dates)
as
(
select cast(@startdate as date) as dates
union all
select dateadd(day, 1, dates) as next_dt
from cod
where DATEADD(day, 1, dates) < @enddate
)
select * from cod
答案 2 :(得分:0)
完成商店程序!!!
在我的案例中,日期必须以文字形式输入, 因为我使用java而且我在我的POO和接口上有关于将date.util转换为date.sql的问题
USE [DB_Demo1]
GO
/****** Object: StoredProcedure [dbo].[showMeReportAssistance] Script Date: 5/04/2017 12:36:46 a. m. ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER proc [dbo].[showMeReportAssistance]
@cod_personal INT,
@startDate VARCHAR(10),
@endDate VARCHAR(10)
as
BEGIN
;WITH CTE AS (
SELECT DATEADD(DD, number, CONVERT(datetime, @startDate, 103)) AS DATES
FROM master.dbo.spt_values
WHERE TYPE = 'P'
AND DATEADD(DD, number, CONVERT(datetime, @startDate, 103)) <= CONVERT(datetime, @endDate, 103)
)
SELECT ISNULL(RA.cod_personal, @cod_personal) AS cod_personal
,cod_schedule
,DATES AS date_mark
,check_in
,check_out
,CASE
WHEN date_mark IS NULL
THEN 'LEFT'
WHEN date_mark IS NOT NULL AND check_in IS NULL
THEN 'LEFT IN'
WHEN date_mark IS NOT NULL AND check_in IS NOT NULL AND check_out IS NOT NULL
THEN 'OK'
WHEN date_mark IS NOT NULL AND check_in IS NOT NULL AND check_in > '09:15:00'
THEN 'LATE'
ELSE 'LEFT'
END AS CONDITION
FROM CTE C
LEFT JOIN ReportAssistence RA ON C.DATES = date_mark
WHERE ISNULL(RA.cod_personal, @cod_personal) = @cod_personal
END