sql server获取最短时间?

时间:2013-01-07 09:49:55

标签: sql sql-server-2008 datetime max min

这是问题,

我有一个名为attendance的表,有4列:

[Username] varchar(256)
[Date] varchar(256)
[Time] varchar(256)
[Action] varchar(256)

我希望获得的是第一次入住和退房时间以及上次入住和退房时间。如果表中只有一个Check In和out行,则返回相同的行。

这样的样本数据:

Username | Date       | Time     | Action
--------------------------------------------
User1    | 01/12/2012 | 12:54:41 | Check In
User1    | 01/12/2012 | 18:26:36 | Check Out
User1    | 01/12/2012 | 18:44:17 | Check In
User1    | 01/12/2012 | 22:05:31 | Check Out

我的预期结果如下:

Output:
Username | Date       | First In | First Out | Last In  | Last Out
User1    | 01/12/2012 | 12:54:41 | 18:26:36  | 18:44:17 | 22:05:31

我试过这个SQL语句:

SELECT [USERNAME], [DATE]
, min(case when [action] = 'Clock In' then [time] else '' end) as 'First in'
, min(case when [action] = 'Clock Out' then [time] else '' end )as 'First out'
, max(case when [action] = 'Clock In' then [time] else '' end) as 'Last in'
, max(case when [action] = 'Clock Out' then [time] else '' end )as 'Last out'
FROM attendance
WHERE [USERNAME] = 'User1' AND [DATE] = '01/12/2012'
group by [username],[date]

它会返回意外的结果,即我的最小值总是''或空,但都是我的最大值 'Last in'和'Last Out'的值正确。

Output:
Username | Date       | First In | First Out | Last In  | Last Out
User1    | 01/12/2012 |          |           | 18:44:17 | 22:05:31

我的SQL有什么问题吗?

任何人都可以提出任何建议吗?

3 个答案:

答案 0 :(得分:2)

我会使用row_number()执行此操作稍微不同:

select username, date,
  max(case when [action] = 'Check In' and rn=1 then time end) FirstIn,
  max(case when [action] = 'Check Out' and rn=1 then time end) FirstOut,
  max(case when [action] = 'Check In' and rn=2 then time end) LastIn,
  max(case when [action] = 'Check Out' and rn=2 then time end) LastOut
from
(
  select username, cast(date as date) date, 
    cast(time as time) time, 
    action,
    row_number() 
      over(partition by username, cast(date as date), action
           order by cast(time as time)) rn
  from attendance
) src
group by username, date;

请参阅SQL Fiddle with Demo

结果是:

| USERNAME |       DATE |          FIRSTIN |         FIRSTOUT |           LASTIN |          LASTOUT |
-----------------------------------------------------------------------------------------------------
|    User1 | 2012-01-12 | 12:54:41.0000000 | 18:26:36.0000000 | 18:44:17.0000000 | 22:05:31.0000000 |

我强烈建议您将datetime存储为datetime数据类型。

注意:我将值从Clock In / Clock Out更改为Check In / Check Out以匹配您提供的示例数据。

答案 1 :(得分:1)

试试这个:

SELECT [USERNAME], [DATE]
, min(case when [action] = 'Clock In' then [time]  end) as 'First in'
, min(case when [action] = 'Clock Out' then [time] end )as 'First out'
, max(case when [action] = 'Clock In' then [time] end) as 'Last in'
, max(case when [action] = 'Clock Out' then [time] end )as 'Last out'
FROM attendance
WHERE [USERNAME] = 'User1' AND [DATE] = '01/12/2012'
group by [username],[date]

你明白问题在哪里吗?

答案 2 :(得分:0)

我的解决方案是创建一个存储过程:

DECLARE @first_in VARCHAR, @first_out VARCHAR, @last_in VARCHAR, @last_out VARCHAR
BEGIN
SELECT TOP 1
     @first_in = time
FROM attendance
WHERE [USERNAME] = 'User1' AND [DATE] = '01/12/2012' AND [ACTION] = 'first in'
ORDER BY time ASC


SELECT TOP 1
     @first_in = time
FROM attendance
WHERE [USERNAME] = 'User1' AND [DATE] = '01/12/2012' AND [ACTION] = 'first out'
ORDER BY time ASC

SELECT TOP 1
     @last_in = time
FROM attendance
WHERE [USERNAME] = 'User1' AND [DATE] = '01/12/2012' AND [ACTION] = 'first in'
ORDER BY time DESC

SELECT TOP 1
     @last_out = time
FROM attendance
WHERE [USERNAME] = 'User1' AND [DATE] = '01/12/2012' AND [ACTION] = 'first out'
ORDER BY time DESC

SELECT 'User1','01/12/2012', @first_in, @first_out, @last_in, @last_out
END