我有一个存储员工登录和注销的数据库,但我们周末没有工作。我的主管希望DTR报告格式(我正在使用RDLC报告)包括周末。 (见附图)
上图是DTR的预期输出格式。我只是想知道如何包括周末,虽然我的数据仅在工作日。是否可以使用SQL Query执行此操作?如果是的话,我应该在sql中使用循环吗?
SQL代码:
select user_id,log_date,login_time,logout_time
from table_DTR
where user_id = 'USER1'
AND log_date BETWEEN '11/21/2014' AND '12/09/2014'
答案 0 :(得分:2)
尝试以下解决方案:
DECLARE @startdate DATE = '11/21/2014' -- your start date
DECLARE @enddate DATE = '12/09/2014' -- your start date
-- create list of all dates between min(log_date) and MAX(log_date)
;WITH cte
AS (SELECT @startdate AS log_date
UNION ALL
SELECT Dateadd(dd, 1, log_date) log_date
FROM cte
WHERE log_date < @enddate)
-- select the data using left outer join so that it will return missing dates too.
SELECT t1.user_id,
c.log_date,
t2.login_time,
t2.logout_time
FROM cte c
CROSS JOIN (SELECT DISTINCT user_id
FROM mytable) t1
LEFT OUTER JOIN mytable t2
ON t2.user_id = t1.user_id
AND t2.log_date = c.log_date
ORDER BY t1.user_id,c.log_date
OPTION(maxrecursion 1000)
它将在周末的时间列中返回null
。
注意:如果您收到错误:The statement terminated. The maximum recursion 100 has been exhausted before statement completion.
,请尝试使用OPTION(maxrecursion 3000)
或更高版本。
答案 1 :(得分:2)
使用公用表表达式并使用from和to date生成日期范围,然后使用CTE作为实际表的左连接。我还没有在左连接中使用user_id过滤器,因此将其应用于您的查询:
DECLARE @TMEP TABLE
(
[Date] DATE,
[IN] VARCHAR(10),
[OUT] VARCHAR(10)
)
INSERT INTO @TMEP VALUES ('2014-11-11','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-12','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-13','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-14','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-15','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-18','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-19','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-20','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-21','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-22','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-25','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-26','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-27','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-28','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-11-29','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-12-1','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-12-2','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-12-3','7:30','5:30')
INSERT INTO @TMEP VALUES ('2014-12-4','7:30','5:30')
DECLARE @FromDate DATE
SET @FromDate = '2014-11-11 06:00:00.000'
DECLARE @ToDate DATE
SET @ToDate = '2014-12-11 06:00:00.000'
;WITH CTE_TableDate ([CTEDate]) as
(
SELECT @FromDate
UNION ALL
SELECT DATEADD(DAY,1,CTEDate) FROM CTE_TableDate WHERE [CTEDate] < @ToDate
)
SELECT
CTE_TableDate.CTEDate,
CASE WHEN DATEPART(DW, CTE_TableDate.CTEDate) = 7 THEN 'SATURDAY'
WHEN DATEPART(DW, CTE_TableDate.CTEDate) = 1 THEN 'SUNDAY'
ELSE TEMP.[In] END AS [IN],
CASE WHEN DATEPART(DW, CTE_TableDate.CTEDate) = 7 THEN 'SATURDAY'
WHEN DATEPART(DW, CTE_TableDate.CTEDate) = 1 THEN 'SUNDAY'
ELSE TEMP.[OUT] END AS [OUT]
FROM CTE_TableDate
LEFT JOIN
(
select
[Date],
[IN],
[OUT]
from
@TMEP) TEMP
ON
CTE_TableDate.CTEDate = TEMP.[Date]
答案 2 :(得分:1)
您可以按如下方式创建日历表:
CREATE TABLE dbo.Calendar
(
dt DATE PRIMARY KEY, -- use SMALLDATETIME if < SQL Server 2008
IsWorkDay BIT
);
DECLARE @s DATE, @e DATE;
SELECT @s = '2000-01-01' , @e = '2029-12-31';
INSERT dbo.Calendar(dt, IsWorkDay)
SELECT DATEADD(DAY, n-1, '2000-01-01'), 1
FROM
(
SELECT TOP (DATEDIFF(DAY, @s, @e)+1) ROW_NUMBER()
OVER (ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
) AS x(n);
SET DATEFIRST 1;
-- weekends
UPDATE dbo.Calendar SET IsWorkDay = 0
WHERE DATEPART(WEEKDAY, dt) IN (6,7);
-- Christmas
UPDATE dbo.Calendar SET IsWorkDay = 0
WHERE MONTH(dt) = 12
AND DAY(dt) = 25
AND IsWorkDay = 1;
然后使用与
相同的内容DECLARE @table_DTR TABLE
( USER_ID VARCHAR(10),
log_date DATE,
login_time TIME,
logout_time TIME)
INSERT INTO @table_DTR VALUES ('USER1','11/21/2014','7:55:00','5:00:00')
select CASE d.IsWorkDay WHEN 0 THEN datename(dw,d.dt) else DTR.user_id END AS user_id,
d.dt AS log_date,
DTR.login_time,
DTR.logout_time
from dbo.Calendar d
LEFT JOIN @table_DTR DTR ON d.dt = DTR.log_date AND DTR.user_id = 'USER1'
WHERE d.dt BETWEEN '11/21/2014' AND '11/26/2014'
有关日历表优缺的详细说明,您可以refer here..