我有一个包含以下行的表:
NAME RFID ACTION TIME DATE
Kashif Islam E2001026770D00742340248A OUT 12:40:00 1/30/2013
Dr.Arshad Ali Shahid E2001026770D0212267009D3 IN 13:52:00 1/30/2013
Qasim Mehmood E2001026770D018223202774 IN 13:52:00 1/30/2013
M.Bilal Khan E2001026770D009522402D80 IN 13:52:00 1/30/2013
Abdul Hameed E2001026770D0181248019B8 IN 13:52:00 1/30/2013
Usman Tariq E2001026770D00862570111D IN 13:52:00 1/30/2013
Dr. Asif Gondal E2001026770D012426600B32 IN 13:52:00 1/30/2013
Dr.Arshad Ali Shahid E2001026770D0212267009D3 OUT 13:52:00 1/30/2013
Dr.Arshad Ali Shahid E2001026770D0212267009D3 IN 13:53:00 1/30/2013
Dr.Arshad Ali Shahid E2001026770D0212267009D3 OUT 13:53:00 1/30/2013
Dr.Arshad Ali Shahid E2001026770D0212267009D3 IN 13:53:00 1/30/2013
Dr.Arshad Ali Shahid E2001026770D0212267009D3 OUT 13:53:00 1/30/2013
Dr.Arshad Ali Shahid E2001026770D0212267009D3 IN 13:54:00 1/30/2013
Dr.Arshad Ali Shahid E2001026770D0212267009D3 OUT 13:54:00 1/30/2013
Aamir Hafeez E2001026770D01952510155B IN 13:55:00 1/30/2013
Amjad Ali Anjum E2001026770D024125401476 IN 13:55:00 1/30/2013
Amjad Ali Anjum E2001026770D024125401476 OUT 13:56:00 1/30/2013
Dr. Asif Gondal E2001026770D012426600B32 OUT 13:56:00 1/30/2013
Arif Shah E2001026770D01852370206D IN 13:56:00 1/30/2013
Fida ul Hassan E2001026770D02112720095C IN 13:56:00 1/30/2013
现在我希望在每个人的指定日期获得最新的ACTION
,例如:
1/30/2013 13:56:00 OUT Amjad Ali Anjum
1/30/2013 13:56:00 IN Arif Shah
1/30/2013 13:56:00 OUT Dr. Asif Gondal
1/30/2013 13:54:00 OUT Dr.Arshad Ali Shahid
1/30/2013 13:56:00 IN Fida ul Hassan
我使用以下查询来获取它,但我得不到正确的结果:
WITH CTE AS (
SELECT
row_number() over (partition by personname order by date) rn,
date,action,time,
personname
FROM
AISDb)
SELECT date,time,action,
personname
FROM CTE WHERE RN = 1 AND datestamp = '1/30/2013'
答案 0 :(得分:8)
我认为你的过滤器位于错误的位置,并且over()子句内的顺序都是错误的。
;WITH CTE AS (
SELECT
row_number() over (partition by personname order by time DESC) rn,
date,action,time,
personname
FROM
AISDb
WHERE datestamp = '20130130')
SELECT date,time,action,
personname
FROM CTE WHERE RN = 1;
如果你需要在IN / OUT的情况下打破平局,两者同时记录,一种方法是打破平局,假设OUT发生在最后:
;WITH CTE AS (
SELECT
row_number() over (partition by personname order by time DESC, action DESC) rn,
date,action,time,
personname
FROM
AISDb
WHERE datestamp = '20130130')
SELECT date,time,action,
personname
FROM CTE WHERE RN = 1;
答案 1 :(得分:2)
经典greatest-n-per-group问题。一种可能的解决方案:
select w.*
from w
inner join (
select name, max(time) time
from w
where date = '2013-01-30'
group by Name
) sel on w.Name = sel.Name
and w.Time = sel.Time
where w.date = '2013-01-30'
小猪背上亚伦的小提琴:http://sqlfiddle.com/#!3/335e4/11
一些注意事项:
答案 2 :(得分:-1)
由于人们的回答表明您需要将日期/时间逻辑的顺序更改为Desc,因此您将获得最新的第一个。另一件事是您只在CTE中按人名进行分区,因此无论日期如何,1值都将是最新值,然后您将日期限制在外部,因此您可能没有匹配的值。您可以通过几种方式解决此问题,但我只是将日期添加到分区逻辑中。
WITH CTE AS
(
SELECT row_number() over (partition by personname, [date] order by [time] desc, rn desc) rn,
[date],
[action],
[time],
personname
FROM (Select row_number() over (Order By (Select Null)) rn,
[date],
[action],
[time],
personname
FROM AISDb)
)
SELECT [date],
[action],
[time],
personname
FROM CTE
WHERE RN = 1
AND datestamp = '1/30/2013'
为了绕过关系,我添加了一个嵌套表,它根据(Select Null)得到一个row_number。这是一个janky变通方法,将获得默认排序。如果这不起作用,则无法使用当前输入执行所需操作,并且应添加标识列以捕获插入顺序。