在sql查询中包含周末

时间:2014-12-15 05:48:49

标签: sql sql-server-2008-r2 formatting reporting rdlc

我有一个存储员工登录和注销的数据库,但我们周末没有工作。我的主管希望DTR报告格式(我正在使用RDLC报告)包括周末。 (见附图

enter image description here

上图是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'

3 个答案:

答案 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..