2017-02-08 3 views
1

У меня есть эта таблица, и я хочу, чтобы поставить номер ранга/строки к строкам со следующим условиемTSQL Помещенный тот же ранг/номер строки на той же колонке А, но приращению раз колонка А изменения

  1. же IO будет имеют такой же ранг/номер строки
  2. Номер ранга/строки увеличивается, как только IO в следующей строке отличается от предыдущей строки.

Таблица отсортирована по AccessDate затем AccessTime и сгруппированы по UserID

Я использую этот запрос, но выход не то, что я хочу, чтобы это было.

SELECT 
    ATTCHECKINOUT.UserID, 
    AccessDate = CAST(CheckTime as date), 
    AccessTime = CAST(CheckTime as time), 
    CheckType, 
    Ranking = DENSE_RANK() over(partition by ATTCHECKINOUT.UserID, CAST(CheckTime as date) order by CheckType) 
FROM ATTCHECKINOUT INNER JOIN ATTUSER ON ATTCHECKINOUT.UserID=ATTUSER.UserID 
WHERE CheckTime BETWEEN '1/6/2017' AND '1/10/2017' AND ATTUSER.BadgeNumber = 10311 
ORDER BY ATTCHECKINOUT.UserID, CheckTime 

Вывод запроса

UserID |AccessDate |AccessTime |IO |Ranking 
8394 |2017-01-06 |11:24:10 |I |1 
8394 |2017-01-06 |11:24:15 |I |1 
8394 |2017-01-06 |13:05:13 |O |2 
8394 |2017-01-06 |13:05:18 |O |2 
8394 |2017-01-06 |13:34:17 |I |1 
8394 |2017-01-06 |13:34:20 |I |1 
8394 |2017-01-06 |20:35:01 |O |2 
8394 |2017-01-06 |20:35:05 |O |2 
8394 |2017-01-07 |10:59:49 |I |1 
8394 |2017-01-07 |10:59:52 |I |1 
8394 |2017-01-07 |17:02:54 |O |2 
8394 |2017-01-07 |17:29:39 |I |1 
8394 |2017-01-07 |17:29:43 |I |1 
8394 |2017-01-07 |20:13:02 |O |2 
8394 |2017-01-07 |20:13:05 |O |2 
8394 |2017-01-09 |08:32:38 |I |1 
8394 |2017-01-09 |08:32:45 |I |1 
8394 |2017-01-09 |20:02:52 |O |2 
8394 |2017-01-09 |20:02:55 |O |2 

Я хочу выход быть как этот

UserID |AccessDate |AccessTime |IO |Ranking 
8394 |2017-01-06 |11:24:10 |I |1 
8394 |2017-01-06 |11:24:15 |I |1 
8394 |2017-01-06 |13:05:13 |O |2 
8394 |2017-01-06 |13:05:18 |O |2 
8394 |2017-01-06 |13:34:17 |I |3 
8394 |2017-01-06 |13:34:20 |I |3 
8394 |2017-01-06 |20:35:01 |O |4 
8394 |2017-01-06 |20:35:05 |O |4 
8394 |2017-01-07 |10:59:49 |I |1 
8394 |2017-01-07 |10:59:52 |I |1 
8394 |2017-01-07 |17:02:54 |O |2 
8394 |2017-01-07 |17:29:39 |I |3 
8394 |2017-01-07 |17:29:43 |I |3 
8394 |2017-01-07 |20:13:02 |O |4 
8394 |2017-01-07 |20:13:05 |O |4 
8394 |2017-01-09 |08:32:38 |I |1 
8394 |2017-01-09 |08:32:45 |I |1 
8394 |2017-01-09 |20:02:52 |O |2 
8394 |2017-01-09 |20:02:55 |O |2 
+0

эта ссылка поможет вам http://stackoverflow.com/questions/41949621/dense-rank-without-duplication/41949896#41949896 –

+0

никакой задержки функции для SQL 2008 –

+0

есть несколько ответов с/без функции задержки .. сделал u chk второй ответ (с рекурсивным cte) ???? –

ответ

0

я использовал свой вывод набора результатов запроса в качестве входных данных. И написал запрос, чтобы получить ожидаемый набор результатов. Вы должны изменить свой порядок заказа с помощью функции dense_rank, увидев ниже запрос.

SELECT UserID, 
     [AccessDate], 
     [AccessTime], 
     [IO], 
     Dense_rank() 
     OVER(
      partition BY UserID, [AccessDate] 
      ORDER BY userid, [AccessDate], Datepart(hour, [AccessTime]), Datepart(minute, [AccessTime]),[IO]) Ranking 
FROM #table1 -- this contains result set of your output query 
+0

проблема с этим, когда часовая и минутная части отличаются для одного и того же IO, рейтинг также будет отличаться, делая вывод неправильным ... –

0

Интересная проблема. Я немного поиграл с этим, и это то, что я придумал. Не самая элегантная вещь, которую я когда-либо производил, но, кажется, поступает правильно. Я использую табличную переменную @t для хранения значений из вашей ATTCHECKINOUT таблицы:

-- prepare test data 
-- note: added some additional rows to test correctness 

declare @t table (
    UserID int not null, 
    CheckTime datetime not null, 
    CheckType nvarchar(1) not null 
) 

insert into @t (UserID, CheckTime, CheckType) 
values 
    (8394 ,'2017-01-06 11:24:10' ,'I'), (8394 ,'2017-01-06 11:24:15' ,'I'), 
    (8394 ,'2017-01-06 13:05:13' ,'O'), (8394 ,'2017-01-06 13:05:18' ,'O'), 
    (8394 ,'2017-01-06 13:34:17' ,'I'), (8394 ,'2017-01-06 13:34:20' ,'I'), 
    (8394 ,'2017-01-06 20:35:01' ,'O'), (8394 ,'2017-01-06 20:35:05' ,'O'), 
    (8394 ,'2017-01-07 10:59:49' ,'I'), (8394 ,'2017-01-07 10:59:52' ,'I'), 
    (8394 ,'2017-01-07 17:02:54' ,'O'), (8394 ,'2017-01-07 17:29:39' ,'I'), 
    (8394 ,'2017-01-07 17:29:43' ,'I'), (8394 ,'2017-01-07 20:13:02' ,'O'), 
    (8394 ,'2017-01-07 20:13:05' ,'O'), (8394 ,'2017-01-07 20:14:08' ,'O'), 
    (8394 ,'2017-01-07 23:14:08' ,'O'), (8394 ,'2017-01-09 08:32:38' ,'I'), 
    (8394 ,'2017-01-09 08:32:45' ,'I'), (8394 ,'2017-01-09 20:02:52' ,'O'), 
    (8394 ,'2017-01-09 20:02:55' ,'O'), (8395 ,'2017-01-06 11:24:10' ,'I'), 
    (8395 ,'2017-01-06 11:24:15' ,'I'), (8395 ,'2017-01-06 13:05:13' ,'O'), 
    (8395 ,'2017-01-06 13:05:18' ,'O'), (8395 ,'2017-01-06 13:09:32' ,'O'), 
    (8395 ,'2017-01-06 13:34:17' ,'I'), (8395 ,'2017-01-06 13:34:20' ,'I') 

-- produce output 

select UserID, 
    cast(CheckTime as date) as AccessDate, 
    cast(CheckTime as time) as AccessTime, 
    CheckType, 
    dense_rank() over (order by groupKey) as [rank] 
from (
    select UserID, CheckTime, CheckType, 
     max(newGroup) over (order by UserId, CheckTime, CheckType ROWS UNBOUNDED PRECEDING) as groupKey 
    from (
     select UserId, 
      CheckTime, 
      CheckType, 
      case 
       when CheckType = lag(CheckType, 1, '') over (order by UserId, CheckTime) 
      then 
       null 
      else 
       row_number() over (order by UserId, CheckTime, CheckType) 
      end as newGroup 
     from @t 
     where CheckTime >= '2017-01-06 13:05:17.000' -- note where clause here 
      and UserID = 8394      -- note where clause here 
    ) as innerSub 
) as outerSub 
order by UserId, CheckTime, CheckType 

Выход:

+--------+------------+------------------+-----------+------+ 
| UserID | AccessDate | AccessTime | CheckType | rank | 
+--------+------------+------------------+-----------+------+ 
| 8394 | 2017-01-06 | 13:05:18.0000000 | O   | 1 | 
| 8394 | 2017-01-06 | 13:34:17.0000000 | I   | 2 | 
| 8394 | 2017-01-06 | 13:34:20.0000000 | I   | 2 | 
| 8394 | 2017-01-06 | 20:35:01.0000000 | O   | 3 | 
| 8394 | 2017-01-06 | 20:35:05.0000000 | O   | 3 | 
| 8394 | 2017-01-07 | 10:59:49.0000000 | I   | 4 | 
| 8394 | 2017-01-07 | 10:59:52.0000000 | I   | 4 | 
| 8394 | 2017-01-07 | 17:02:54.0000000 | O   | 5 | 
| 8394 | 2017-01-07 | 17:29:39.0000000 | I   | 6 | 
| 8394 | 2017-01-07 | 17:29:43.0000000 | I   | 6 | 
| 8394 | 2017-01-07 | 20:13:02.0000000 | O   | 7 | 
| 8394 | 2017-01-07 | 20:13:05.0000000 | O   | 7 | 
| 8394 | 2017-01-07 | 20:14:08.0000000 | O   | 7 | 
| 8394 | 2017-01-07 | 23:14:08.0000000 | O   | 7 | 
| 8394 | 2017-01-09 | 08:32:38.0000000 | I   | 8 | 
| 8394 | 2017-01-09 | 08:32:45.0000000 | I   | 8 | 
| 8394 | 2017-01-09 | 20:02:52.0000000 | O   | 9 | 
| 8394 | 2017-01-09 | 20:02:55.0000000 | O   | 9 | 
+--------+------------+------------------+-----------+------+ 

EDIT: Вот новая версия, которая работает на SQL Server 2008. подготовка данных теста такая же, как и раньше.

;with cte as (
    select UserID, CheckTime, CheckType, 
     (case when sub.CheckType != sub.PrevCheckType then sub.RowNum else null end) as Indicator 
    from (
     select UserID, CheckTime, CheckType, 
      ISNULL((
       select top 1 CheckType 
       from @t as innerT 
       where t.UserID = innerT.UserID 
        and t.CheckTime > innerT.CheckTime 
       order by UserID, CheckTime desc), '') as PrevCheckType 
      , row_number() over (order by UserID, CheckTime, CheckType) as RowNum 
     from @t as t 
     where CheckTime >= '2017-01-06 13:05:17.000' -- note where clause here 
      and UserID = 8394      -- note where clause here 
    ) sub 
) 
select UserID, 
    cast(CheckTime as date) as AccessDate, 
    cast(CheckTime as time) as AccessTime, 
    CheckType, 
    dense_rank() over (partition by UserID order by UserID, ISNULL(Indicator, (select top 1 Indicator from cte innerCte where outerCte.UserID = innerCte.UserID and outerCte.CheckTime > innerCte.CheckTime and Indicator is not null order by UserID, CheckTime desc))) as [Rank] 
from cte outerCte 
order by UserID, CheckTime, CheckType 

Эта версия может быть легко модифицирован для работы также на Sql Server 2005. Просто исправить подготовить тестовые данные часть и не использовать date и time бросает на выходе.

+0

спасибо за ответ, но, к сожалению, только с использованием SQL Server 2008, без функции задержки для этой версии sql –

+0

@DennisLim Вы заметили, что я добавил отдельный образец для Sql Server 2008? – user1429080