根据主查询中的某些条件选择特定年份的虚拟数据

时间:2015-04-07 10:30:33

标签: sql sql-server-2008

以下查询返回员工的所有ExceptionDays:

SELECT
     idEmployee, idExceptionDayType,
     YEAR(startDate) year,
     SUM (days) total
 FROM
     ExceptionDays ed
GROUP BY idEmployee, idExceptionDayType, YEAR(startDate)

我需要从员工的招聘年份开始生成虚拟ExceptionDays,直到当前年份。如果当前员工的ExceptionDays表中已存在一年,则此子查询不应创建虚拟数据。

所以基本上,如果员工在2010年被聘用并且它在2014年和2015年的ExceptionDays表中有数据,那么查询应该返回2010,2011,2012,2013作为虚拟数据,而对于2014年和2015年,它应该得到有效数据

为了生成虚拟数据,我使用了几年的临时日历:

 SELECT 
    1 as idEmployee,1 as idExceptionDayType,YEAR(c.date) year,0 total
   FROM 
     TMP_CALENDAR c WITH (NOLOCK)
  WHERE
     YEAR(c.date) >= 2012
 AND YEAR(c.date) < YEAR(GETDATE())
GROUP BY YEAR(c.date)

第二个子查询应该以某种方式连接到第一个查询,期望的查询将变为:

   SELECT 
         ED.idEmployee,1 as idExceptionDayType,YEAR(c.date) year,0 total
       FROM 
         TMP_CALENDAR c WITH (NOLOCK)
         JOIN Employees E ON ED.idEmployee = E.idEmployee
      WHERE
         YEAR(c.date) >= YEAR(e.hiringDate)
     AND YEAR(c.date) < YEAR(GETDATE()) AND YEAR <> YEAR(ed.year)
    GROUP BY YEAR(c.date)

我们可以看到需要对第一个查询进行ED引用,因此查询会变得有效,但我不确定我该怎么做。

有人可以帮我一点点吗? 提前谢谢,

2 个答案:

答案 0 :(得分:1)

这种类型的查询背后的想法是首先生成输出行 - 使用CROSS JOIN获取所有年份和员工,然后使用其他逻辑来引入其他值。

以下版本仅使用ExceptionDays来获取所有年份,假设每年至少有一天这样。您还可以使用y子查询的日历表:

SELECT e.idEmployee, COALESCE(ed.idExceptionDayType, 1) as idExceptionDayType
      y.year, COALESCE(SUM(ed.days), 0) as total
FROM (SELECT DISTINCT idEmployee FROM ExceptionDays) e CROSS JOIN
     (SELECT DISTINCT YEAR(startDate) as year FROM ExceptionDays) y LEFT JOIN
     ExceptionDays ed
     ON ed.idEmployee = e.idEmployee and
        y.year BETWEEN YEAR(ed.startDate) AND year(GETDATE())
GROUP BY e.idEmployee, ed.idExceptionDayType, y.year

答案 1 :(得分:0)

你可以尝试这样的事情。

  1. 从日历中获取所有不同的年份
  2. 与所有员工交叉加入并过滤以仅获得员工加入后的那些年
  3. 仅筛选那些在特定年份的ExceptionDays中没有条目的员工
  4. <强>查询

       SELECT 
             E.idEmployee,1 as idExceptionDayType,calendar_year,0 total
           FROM 
             (
                SELECT YEAR(c.date) calendar_year
                FROM TMP_CALENDAR
                GROUP BY YEAR(c.date)
             )c
             CROSS JOIN Employees E
             LEFT JOIN ExceptionDays ed
             ON ED.idEmployee = E.idEmployee
             AND ed.YEAR(startDate) = calendar_year
          WHERE calendar_year >= YEAR(e.hiringDate)
            AND calendar_year < YEAR(GETDATE())
            AND ED.idEmployee IS NULL