这是问题,
我有一个名为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有什么问题吗?
任何人都可以提出任何建议吗?
答案 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;
结果是:
| 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 |
我强烈建议您将date
和time
存储为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