SQL日期范围 - 按案例分组和最小最大值

时间:2017-04-17 07:09:57

标签: sql sql-server sql-server-2012

我的查询如下:

SELECT 
CASE a.SkedName WHEN 'Restday' THEN 1 WHEN 'No Schedule' THEN 2 ELSE 3 END AS TS,
DateAdd(Year,2,TDate) TDate,
CASE a.SkedName WHEN 'Restday' THEN '00:00:00' WHEN 'No Schedule' THEN '00:00:00' ELSE SchedTI END AS SchedTimeIn,
DateAdd(Year,2,TDate) AS DateTimeIn,
DateAdd(Year,2,TDate) AS DateTimeOut,
left(emp_firstname,1) + '. '  + left(emp_middlename,1) + '. ' + emp_lastname empName,
SkedName
FROM EmpList a
    INNER JOIN tbl_employee b ON a.EmpId = b.emp_id
    ORDER BY SchedTimeIn, a.SkedName, emp_lastname, emp_firstname

返回此结果:

TS  TDate       SchedTimeIn DateTimeIn  DateTimeOut empName         SkedName

2   2017-04-01  00:00:00    2017-04-01  2017-04-01  L. C. Manalo    No Schedule
2   2017-04-02  00:00:00    2017-04-02  2017-04-02  L. C. Manalo    No Schedule
2   2017-04-03  00:00:00    2017-04-03  2017-04-03  L. C. Manalo    No Schedule
2   2017-04-04  00:00:00    2017-04-04  2017-04-04  L. C. Manalo    No Schedule
1   2017-04-04  00:00:00    2017-04-04  2017-04-04  J. S. Bio       Restday
1   2017-04-05  00:00:00    2017-04-05  2017-04-05  J. S. Bio       Restday
3   2017-04-27  09:00:00    2017-04-27  2017-04-27  R. M. Jakosalem 9:00-6:00 Semi-Flexi
3   2017-04-28  09:00:00    2017-04-28  2017-04-28  R. M. Jakosalem 9:00-6:00 Semi-Flexi
3   2017-04-29  09:00:00    2017-04-29  2017-04-29  R. M. Jakosalem 9:00-6:00 Semi-Flexi

但是,我希望的结果是删除“无计划”和“休息日”计划类型的冗余。

而不是:

TS  TDate       SchedTimeIn DateTimeIn  DateTimeOut empName         SkedName

2   2017-04-01  00:00:00    2017-04-01  2017-04-01  L. C. Manalo    No Schedule
2   2017-04-02  00:00:00    2017-04-02  2017-04-02  L. C. Manalo    No Schedule
2   2017-04-03  00:00:00    2017-04-03  2017-04-03  L. C. Manalo    No Schedule
2   2017-04-04  00:00:00    2017-04-04  2017-04-04  L. C. Manalo    No Schedule
1   2017-04-04  00:00:00    2017-04-04  2017-04-04  J. S. Bio       Restday
1   2017-04-05  00:00:00    2017-04-05  2017-04-05  J. S. Bio       Restday

我想要的结果是将TDate设置为SkedName的最大日期,将DateTimeIn设置为MinDate,将DateTimeOut设置为每个员工的“No Schedule”和“Restday”的MaxDate以避免过多行:

TS  TDate       SchedTimeIn DateTimeIn  DateTimeOut empName         SkedName

2   2017-04-04  00:00:00    2017-04-01  2017-04-04  L. C. Manalo    No Schedule
1   2017-04-05  00:00:00    2017-04-04  2017-04-05  J. S. Bio       Restday

我试过“GROUP BY SkedName HAVING SkedName ='No Schedule'Et SkedName ='Restday'”。但它给了我一个错误

  

列'EmpList.TDate'在选择列表中无效,因为它不是   包含在聚合函数或GROUP BY子句中。

我不知道该怎么办。我感谢任何答案和建议。急需帮助:(非常感谢。

3 个答案:

答案 0 :(得分:1)

您可以使用下面的cte和dense_rank()来实现它

;With cte as
(    
    SELECT 
    CASE a.SkedName WHEN 'Restday' THEN 1 WHEN 'No Schedule' THEN 2 ELSE 3 END AS TS,
    DateAdd(Year,2,TDate) TDate,
    CASE a.SkedName WHEN 'Restday' THEN '00:00:00' WHEN 'No Schedule' THEN '00:00:00' ELSE SchedTI END AS SchedTimeIn,
    DateAdd(Year,2,TDate) AS DateTimeIn,
    DateAdd(Year,2,TDate) AS DateTimeOut,
    left(emp_firstname,1) + '. '  + left(emp_middlename,1) + '. ' + emp_lastname empName,
    SkedName,
    dense_rank() over (partition by a.EmpId,SkedName order by DateAdd(Year,2,TDate)) as rn,
    a.EmpId as empid
    FROM EmpList a
    INNER JOIN tbl_employee b ON a.EmpId = b.emp_id
)
 Select TS,TDate,SchedTimeIn,DateTimeIn,
 case when skedname in ('No Schedule','Restday')
 then
  (Select top 1 DateTimeOut from cte where rn = (select max(rn) from cte cin where cin.empid=cout.empid and cin.skedName = cout.skedName) and empid=cout.empid and skedName=cout.skedName) 
 else
  DateTimeOut end as DateTimeOut,
 empName,SkedName
 from cte cout where rn=1 or skedName not in ('No Schedule','Restday')
 ORDER BY SchedTimeIn, SkedName, emp_lastname, emp_firstname 

答案 1 :(得分:1)

尝试:

select Min(DateTimeIn),Max(DateTimeOut),empname,SkedName from Emplist group by empname,SkedName

答案 2 :(得分:1)

根据我的理解,

我现在已经编辑了我的答案。

    ;WITH cte 
     AS (SELECT ts, 
                tdate, 
                schedtimein, 
                datetimein, 
                datetimeout, 
                empname, 
                skedname, 
                Row_number() 
                  OVER( 
                    partition BY skedname 
                    ORDER BY datetimein)       AS Rn_in, 
                Row_number() 
                  OVER( 
                    partition BY skedname 
                    ORDER BY datetimeout DESC) AS Rn_out 
         FROM   (SELECT CASE a.skedname 
                          WHEN 'Restday' THEN 1 
                          WHEN 'No Schedule' THEN 2 
                          ELSE 3 
                        END                                             AS TS, 
                        Dateadd(year, 2, tdate)                         TDate, 
                        CASE a.skedname 
                          WHEN 'Restday' THEN '00:00:00' 
                          WHEN 'No Schedule' THEN '00:00:00' 
                          ELSE schedti 
                        END                                             AS SchedTimeIn, 
                        Dateadd(year, 2, tdate)                         AS DateTimeIn, 
                        Dateadd(year, 2, tdate)                         AS DateTimeOut, 
                        LEFT(emp_firstname, 1) + '. ' 
                        + LEFT(emp_middlename, 1) + '. ' + emp_lastname empName, 
                        skedname 
                 FROM   emplist a 
                        INNER JOIN tbl_employee b 
                                ON a.empid = b.emp_id)A), 
     cte1 
     AS (SELECT a.ts, 
                b.tdate, 
                a.schedtimein, 
                a.datetimein, 
                b.datetimeout, 
                a.empname, 
                a.skedname, 
                a.rn_in, 
                b.rn_out 
         FROM   cte a 
                JOIN cte b 
                  ON a.ts = b.ts 
                     AND a.rn_in = b.rn_out 
         WHERE  a.skedname IN ( 'No Schedule', 'Restday' )) SELECT ts, 
       tdate, 
       schedtimein, 
       datetimein, 
       datetimeout, 
       empname, 
       skedname 
FROM   cte1 
WHERE  rn_in = 1 
UNION 
SELECT ts, 
       tdate, 
       schedtimein, 
       datetimein, 
       datetimeout, 
       empname, 
       skedname 
FROM   cte 
WHERE  skedname NOT IN ( 'No Schedule', 'Restday' ) 

注意:我使用了Row_number函数。