Sql 如何找到一天中的第一个时间和最后一个时间

Sql 如何找到一天中的第一个时间和最后一个时间,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我有一个查询,它抓住了第一个打卡的部门的人,以及最后一个打卡的部门的人。基本上,这显示了谁打开了一个位置,谁关闭了一个位置。下面是我的查询,我正在使用OVER函数,但是OVER函数不适用于VB.net中的数据集。是否有其他选项可以替换OVER函数 SELECT * FROM ( SELECT timeclock.dtTimeIn, timeclock.dtTimeOut, employees.sfirstname, RANK() OVER ( ORDER BY dtTime

我有一个查询,它抓住了第一个打卡的部门的人,以及最后一个打卡的部门的人。基本上,这显示了谁打开了一个位置,谁关闭了一个位置。下面是我的查询,我正在使用OVER函数,但是OVER函数不适用于VB.net中的数据集。是否有其他选项可以替换OVER函数

SELECT * FROM (
    SELECT timeclock.dtTimeIn, timeclock.dtTimeOut, employees.sfirstname,
       RANK() OVER ( ORDER BY dtTimeIn) rk1, --earliest record gets 1
       RANK() OVER (ORDER BY dtTimeOut DESC) rk2 --latest record gets 1

    FROM   TimeClock INNER JOIN
                         Employees ON TimeClock.lEmployeeID = Employees.lEmployeeID
    WHERE (dtTimeIn > dateadd(day, datediff(day, 0, getdate())-1, 0)) AND (dtTimeOut < dateadd(day, datediff(day, 0, getdate()), 0)) AND 
      (sDept IN ('1', '2', '3'))
) A
WHERE rk2=1 

可以将其替换为相关子查询。以下是rk1的一个示例:


Rank可以生成多个记录,当存在联系时,所有记录都标记为1。如果您真的是指行数,那么您可以在上面的查询中使用count*,而不是countdistinct。

您的查询只需返回关闭位置的人

要返回谁打开和谁关闭,需要将where子句更改为

where rk2 = 1 or rk1 = 1
如果您将同时从多个sDept中获得,那么应该像这样为sDept划分顺序

RANK() OVER ( partition by sDept ORDER BY dtTimeIn) rk1, --earliest record gets 1
           RANK() OVER ( partition by sDept ORDER BY dtTimeOut DESC) rk2 --latest record get

设置环境设置以运行查询

    declare @TimeClock table ( lEmployeeID int, dtTimeIn datetime, dtTimeOut datetime)
    declare @Employees table ( lEmployeeID int, sfirstname varchar(max),sDept varchar(max))
    declare @getDate date
    set @getDate ='02/12/2013' 

    insert @Employees 
    values (1,'Ana','1')
    ,(2,'Pedro','1')
    ,(3,'Alfred','2')

    insert @TimeClock
    values (1 ,'02/12/2013 08:30','02/11/2013 11:30')
    ,(2 ,'02/12/2013 08:00','02/11/2013 11:00')
    ,(3 ,'02/12/2013 08:15','02/11/2013 11:15')
你的问题

    SELECT * FROM (
        SELECT timeclock.dtTimeIn, timeclock.dtTimeOut, employees.sfirstname,
           RANK() OVER (partition by sDept  ORDER BY dtTimeIn) rk1, --earliest record gets 1
           RANK() OVER (partition by sDept  ORDER BY dtTimeOut DESC) rk2 --latest record gets 1

        FROM   @TimeClock timeclock
        INNER JOIN @Employees Employees
        ON TimeClock.lEmployeeID = Employees.lEmployeeID
        WHERE (dtTimeIn > dateadd(day, datediff(day, 0, @getDate)-1, 0)) AND (dtTimeOut < dateadd(day, datediff(day, 0, @getDate), 0)) AND 
          (sDept IN ('1', '2', '3'))
    ) A
    WHERE rk2=1 
看。。结果集中是谁关闭的

正在更改where子句

SELECT * FROM (
        SELECT timeclock.dtTimeIn, timeclock.dtTimeOut, employees.sfirstname,
           RANK() OVER ( ORDER BY dtTimeIn) rk1, --earliest record gets 1
           RANK() OVER (ORDER BY dtTimeOut DESC) rk2 --latest record gets 1

        FROM   @TimeClock timeclock
        INNER JOIN @Employees Employees
        ON TimeClock.lEmployeeID = Employees.lEmployeeID
        WHERE (dtTimeIn > dateadd(day, datediff(day, 0, @getDate)-1, 0)) AND (dtTimeOut < dateadd(day, datediff(day, 0, @getDate), 0)) AND 
          (sDept IN ('1', '2', '3'))
    ) A
    WHERE rk2=1 
    or rk1 = 1
佩德罗打开了sDept'1',安娜关闭了sDept'2',阿尔弗雷德打开了sDept'2',

您可以尝试以下方法:

SELECT  tc.dtTimeIn
        , tc.dtTimeOut
        , e.sfirstname
FROM    TimeClock tc
JOIN    Employees e ON tc.lEmployeeID = e.lEmployeeID
JOIN    (               
            SELECT  DATEADD(DAY, DATEDIFF(DAY, 0, tc.dtTimeIn), 0) _date
                    , MIN(tc.dtTimeIn) dtTimeIn
                    , MAX(tc.dtTimeOut) dtTimeOut
            FROM    TimeClock tc
            WHERE   e.sDept IN ('1', '2', '3')
            GROUP BY
                    DATEADD(DAY, DATEDIFF(DAY, 0, tc.dtTimeIn), 0)
) t ON  t._date = DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
AND     DATEADD(DAY, DATEDIFF(DAY, 0, tc.dtTimeIn), 0) = t._date
AND     (t.dtTimeIn = tc.dtTimeIn OR t.dtTimeOut = tc.dtTimeOut)
WHERE   e.sDept IN ('1', '2', '3')

如果您将代码放入存储过程中,为什么VB.Net会关心您是否使用它来派生结果?或者视图。但你确定它不起作用吗?where子句应该是where rk2=1还是rk1=1?哪个版本的VB.net reporting不能将SQL语句传递给SQL Server?为什么VB.net关心SQL语法的外观?它应该将其传递给SQL Server。什么是不正常工作?你收到错误信息了吗?如果是这样的话,那是什么呢?好吧,当你说,医生,当我做x的时候很痛,我会说当医生说不要做x的时候你不应该感到惊讶。换言之,您正在尝试使用一些我们大多数人一开始都不会使用的拖放界面。为什么要用不懂t-SQL的东西?@AaronBertrand我感谢你的侮辱。我的理解是stackoverflow的想法是获得帮助,并分享知识?我在寻找一个问题的答案。如果你有一个更好的方法,那么提供关于如何得到最终答案的见解也许是很好的。有些人不如你先进。。。我想提醒你,你也曾经在我的位置上。。。我肯定你得到了某种帮助。我不是在寻找答案,只是在寻找找到答案的方法。。。我什么都不知道,除了拖放。。。尽管如此,我愿意学习你是对的。我没有发布第二个问题。问题是,我如何在不使用OVER的情况下完成此操作,以便使用report。我假设Date不是2005 SQL函数?@Shmewnix您现在可以尝试此查询,我将其调整为SQL Server 2005。这实际上非常接近。我改变了一些事情,但出于某种原因,它抓住了第二个人的第二个插针。所以它显示部门里有两个人7:30进来。这是正常的,然后显示第二个人也在11:03打卡。。。它应该只在7:30显示打卡,知道吗?它显示:“2013年12月2日7:30:00 Fred 2013年12月2日7:30:00 Timothy 2013年12月2日11:34:00 Timothy”你的答案足够接近了。它把我带到了我需要的地方。我不敢相信我以前没有尝试过最小值或最大值函数。。。我对排名太着迷了。谢谢
SELECT * FROM (
        SELECT timeclock.dtTimeIn, timeclock.dtTimeOut, employees.sfirstname,
           RANK() OVER ( ORDER BY dtTimeIn) rk1, --earliest record gets 1
           RANK() OVER (ORDER BY dtTimeOut DESC) rk2 --latest record gets 1

        FROM   @TimeClock timeclock
        INNER JOIN @Employees Employees
        ON TimeClock.lEmployeeID = Employees.lEmployeeID
        WHERE (dtTimeIn > dateadd(day, datediff(day, 0, @getDate)-1, 0)) AND (dtTimeOut < dateadd(day, datediff(day, 0, @getDate), 0)) AND 
          (sDept IN ('1', '2', '3'))
    ) A
    WHERE rk2=1 
    or rk1 = 1
        dtTimeIn            dtTimeOut               sfirstname  rk1 rk2
    2013-02-12 08:30:00.000 2013-02-11 11:30:00.000 Ana     3   1

    2013-02-12 08:00:00.000 2013-02-11 11:00:00.000 Pedro   1   3
2013-02-12 08:15:00.000 2013-02-11 11:15:00.000 Alfred  1   1
SELECT  tc.dtTimeIn
        , tc.dtTimeOut
        , e.sfirstname
FROM    TimeClock tc
JOIN    Employees e ON tc.lEmployeeID = e.lEmployeeID
JOIN    (               
            SELECT  DATEADD(DAY, DATEDIFF(DAY, 0, tc.dtTimeIn), 0) _date
                    , MIN(tc.dtTimeIn) dtTimeIn
                    , MAX(tc.dtTimeOut) dtTimeOut
            FROM    TimeClock tc
            WHERE   e.sDept IN ('1', '2', '3')
            GROUP BY
                    DATEADD(DAY, DATEDIFF(DAY, 0, tc.dtTimeIn), 0)
) t ON  t._date = DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
AND     DATEADD(DAY, DATEDIFF(DAY, 0, tc.dtTimeIn), 0) = t._date
AND     (t.dtTimeIn = tc.dtTimeIn OR t.dtTimeOut = tc.dtTimeOut)
WHERE   e.sDept IN ('1', '2', '3')