运行查询,然后为该查询的每个结果运行查询

时间:2015-02-19 11:48:35

标签: sql sql-server

我正在尝试创建一个查询,在给定的日期范围内告诉我某人是否缺席。到目前为止,我有两个查询,一个用于获取每个人和日期,如果他们被安排在,一个如果你通过它,那个人的卡代码告诉你他们在时钟上刷了多少次在终端中,一些滑动> 0会告诉我他们是否在。

以下是获取每个人的第一个查询以及他们应该参加的日期。

      SELECT
      CHINA_VISION_PubCards.CardNo,
      CHINA_VISION_PubPersonnel.Name,
      LEFT(CONVERT(DATE, ATDScheduling.ScheduleDate), 11) AS Date1
    FROM CHINA_VISION_PubPersonnel
      INNER JOIN
      CHINA_VISION_DorEvents ON CHINA_VISION_PubPersonnel.Reference = CHINA_VISION_DorEvents.Reference
      INNER JOIN
      CHINA_VISION_PubCards ON CHINA_VISION_PubPersonnel.Reference = CHINA_VISION_PubCards.PubPersonnel_Ref
      RIGHT OUTER JOIN
      ATDScheduling ON CHINA_VISION_PubPersonnel.Reference = ATDScheduling.PubPersonnel_Ref
    WHERE
      (ATDScheduling.ScheduleDate BETWEEN '2015-02-12' AND '2015-02-22') AND (CHINA_VISION_PubPersonnel.Name <> 'null') AND
      (ATDScheduling.ATDShift_Ref > 1)
    ORDER BY CHINA_VISION_PubPersonnel.Name

此查询产生如下结果:

  ClockNo |  Name     | Date should be in 
    5726    Person 1    2015-02-14
    5726    Person 1    2015-02-15
    5726    Person 1    2015-02-21
    5726    Person 1    2015-02-22
    5728    Person 2    2015-02-13
    5728    Person 2    2015-02-14
    5728    Person 2    2015-02-15
    5728    Person 2    2015-02-20
    5728    Person 2    2015-02-21
    5728    Person 2    2015-02-22
    5736    Person 3    2015-02-12
    5736    Person 3    2015-02-13
    5736    Person 3    2015-02-14

这是第二个查询以及传递卡片代码和日期时的结果。

SELECT COUNT(*) AS Count
FROM CHINA_VISION_DorEvents
  INNER JOIN
  CHINA_VISION_PubCards ON CHINA_VISION_DorEvents.CardCode = CHINA_VISION_PubCards.CardCode
WHERE (CHINA_VISION_DorEvents.EventTM BETWEEN CONVERT(DATETIME, '2015-02-12 00:00:00', 102) AND CONVERT(DATETIME,102)) AND
  (CHINA_VISION_DorEvents.DorCtrls_Ref = '16')
GROUP BY CHINA_VISION_PubCards.CardNo
HAVING (CHINA_VISION_PubCards.CardNo = '5726')

这个查询会有这样的输出:

Count 
  4

如果计数高于0,那么他们就会在时钟机器上刷卡,表明它们已经进入。他们刷卡的数量并不重要,只要它高于0

所以对于缺席,如果计数为0,则它​​们不存在,并且应该将计数器增加一个

如果可能的话,我希望查询的内容看起来像是一起组合的

Clock Number  |    Name    |     Absence count
   5725           person 1             3
   5728           person 2             0 

等等。

2 个答案:

答案 0 :(得分:2)

我喜欢CTE的可读性,并且使用NOT EXISTS和OUTER APPLY因为它通常更快,但是至少有4或5种不同的方式来编写这个查询。这是一个展示如何获得缺席的例子。我还删除了一些不需要的代码并简化了查询。更多评论内联:

/*
Since staff are always on the schedule (otherwise how could they be absent?), 
and we need their cards for the next query, let's do all INNER joins here.
We get one row per staffer, per day.
*/
With ScheduleCTE AS (
    SELECT
        c.CardNo,
        p.Name,
        s.ScheduleDate
    FROM
        ATDScheduling s
        INNER JOIN CHINA_VISION_PubPersonnel p ON p.Reference = s.PubPersonnel_Ref
        INNER JOIN CHINA_VISION_PubCards c ON p.Reference = c.PubPersonnel_Ref
    WHERE
        s.ScheduleDate BETWEEN '2015-02-12' AND '2015-02-22'
        AND s.ATDShift_Ref > 1
)


/* 
not sure if your EventTM field includes time, so I'm trimming the time off both date fields to be safe. 
This slows the query, so avoid the type conversion if not necessary!
*/

SELECT
    s.CardNo,
    s.Name,
    COUNT(*) AS AbsentCount
FROM
    ScheduleCTE s
WHERE 
    NOT EXISTS (
    --if staffer was present, let's remove him from the result
        SELECT TOP 1 1
        FROM 
            CHINA_VISION_DorEvents e
        WHERE 
            e.CardCode = s.CardCode
            AND CAST(FLOOR(CAST(s.Date1 AS FLOAT)) AS DATETIME) = CAST(FLOOR(CAST(e.EventTM AS FLOAT)) AS DATETIME)
        )
GROUP BY
    s.CardNo,
    s.Name
ORDER BY s.Name
;

答案 1 :(得分:1)

这是一个WITH语句示例。未经测试,因为我不能100%确定您的查询是如何工作的,而且我很快就完成了。基本上使用WITH在ORDER BY CHINA_VISION_PubPersonnel.Name之后的第二个SELECT语句中查询Clocks_CTE;在WITH之前需要

Kahn可能有更好的想法,但也许这是一个开始。

--This is the first query which is stored in Clocks_CTE
;WITH Clocks_CTE
    (SELECT CHINA_VISION_PubCards.CardNo AS [ClockNum],
            CHINA_VISION_PubPersonnel.Name AS [Name],
            LEFT(CONVERT(DATE, ATDScheduling.ScheduleDate), 11) AS [Date1]
    FROM CHINA_VISION_PubPersonnel
       INNER JOIN
           CHINA_VISION_DorEvents ON CHINA_VISION_PubPersonnel.Reference = CHINA_VISION_DorEvents.Reference
       INNER JOIN
           CHINA_VISION_PubCards ON CHINA_VISION_PubPersonnel.Reference = CHINA_VISION_PubCards.PubPersonnel_Ref
       RIGHT OUTER JOIN
           ATDScheduling ON CHINA_VISION_PubPersonnel.Reference = ATDScheduling.PubPersonnel_Ref
    WHERE (ATDScheduling.ScheduleDate BETWEEN '2015-02-12' 
    AND '2015-02-22') 
    AND (CHINA_VISION_PubPersonnel.Name <> 'null') 
    AND (ATDScheduling.ATDShift_Ref > 1)
    ORDER BY CHINA_VISION_PubPersonnel.Name)
-- End Clocks_CTE
-- You can now do a query on Clocks_CTE
-- Basic example query that you would need to modify
SELECT Count(ClockNum) AS [AbsenceCount],
       c.Name,
       c.ClockNum
FROM Clocks_CTE c
    INNER JOIN CHINA_VISION_DorEvents.CardCode ON c.ClockNum
WHERE (c.Date1 BETWEEN CONVERT(DATETIME, '2015-02-12 00:00:00', 102) AND CONVERT(DATETIME,102)) 
AND (CHINA_VISION_DorEvents.DorCtrls_Ref = '16')
GROUP BY c.ClockNum
         c.Name
ORDER BY c.ClockNum