Вычисление промежуточного результата при изменении значения в разделе - PullRequest
0 голосов
/ 18 июня 2020

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

Постановка проблемы:
Я хочу рассчитать последовательность передачи, показывающую, когда человек менял местоположение, на основе соответствующего идентификатора местоположения с течением времени.

Примеры данных (Таблица1)

+----------+------------+-----------+---------+
| PersonID | LocationID | Date      | Time    |
+----------+------------+-----------+---------+
| 12       | A          | 6/17/2020 | 12:00PM |
+----------+------------+-----------+---------+
| 12       | A          | 6/18/2020 | 1:00PM  |
+----------+------------+-----------+---------+
| 12       | B          | 6/18/2020 | 6:00AM  |
+----------+------------+-----------+---------+
| 12       | C          | 6/19/2020 | 3:00PM  |
+----------+------------+-----------+---------+
| 13       | A          | 6/16/2020 | 8:00AM  |
+----------+------------+-----------+---------+
| 13       | A          | 6/16/2020 | 11:00AM |
+----------+------------+-----------+---------+
| 13       | A          | 6/16/2020 | 12:00AM |
+----------+------------+-----------+---------+
| 13       | B          | 6/16/2020 | 4:00PM  |
+----------+------------+-----------+---------+

Ожидаемые результаты

+----------+------------+-----------+---------+-------------------+
| PersonID | LocationID | Date      | Time    | Transfer Sequence |
+----------+------------+-----------+---------+-------------------+
| 12       | A          | 6/17/2020 | 12:00PM | 1                 |
+----------+------------+-----------+---------+-------------------+
| 12       | A          | 6/18/2020 | 1:00PM  | 1                 |
+----------+------------+-----------+---------+-------------------+
| 12       | B          | 6/18/2020 | 6:00AM  | 2                 |
+----------+------------+-----------+---------+-------------------+
| 12       | C          | 6/19/2020 | 3:00PM  | 3                 |
+----------+------------+-----------+---------+-------------------+
| 13       | A          | 6/16/2020 | 8:00AM  | 1                 |
+----------+------------+-----------+---------+-------------------+
| 13       | A          | 6/16/2020 | 11:00AM | 1                 |
+----------+------------+-----------+---------+-------------------+
| 13       | A          | 6/16/2020 | 12:00AM | 1                 |
+----------+------------+-----------+---------+-------------------+
| 13       | B          | 6/16/2020 | 4:00PM  | 2                 |
+----------+------------+-----------+---------+-------------------+

Что я пробовал

SELECT 
     [t1].[PersonID]
    ,[t1].[LocationID]
    ,[t1].[Date]
    ,[t1].[Time]
    ,DENSE_RANK() 
         OVER( 
           partition BY [t1].[PersonID], [t1].[LocationID] 
           ORDER BY [t1].[Date] ASC, [t1].[Time] ASC) AS 
       [Transfer Sequence]


FROM Table1 [t1]

К сожалению, я считаю, что DENSE_RANK () присваивает рейтинг независимо от того, изменилось ли значение LocationID. Мне нужна функция, которая добавит только один в последовательность, когда изменится LocationID.

Любая помощь будет принята с благодарностью.

Спасибо!

Ответы [ 2 ]

1 голос
/ 18 июня 2020
• 1000 1001 *
DECLARE transaction CURSOR
FOR select PersonID, LocationID, Date, Time from table1;

Затем al oop:

OPEN CURSOR transaction
set @count = 0
set @person_saved = ""
set @location_saed = ""
FETCH NEXT FROM transaction INTO @person, @location, @date, @time

WHILE @@FETCH_STATUS = 0  
BEGIN
if @person_saved <> @person  -- changing personID, reset count
begin
set count = 0
set persone_saved = @person
end
if @location_saved <> @location. -- changing location, add count
begin
set @count = @count + 1
set @location_saved = @location
end
update table1 set sequence = @count where PersonId = @person and locationId = @location and date = @date and time = @time

FETCH NEXT FROM transaction INTO @person, @location, @date, @time
END

CLOSE transaction
DEALLOCATE transaction
1 голос
/ 18 июня 2020

Вы хотите поместить «соседние» строки в одну группу. Прямые оконные функции не могут сделать это за вас - нам потребуется использовать технику промежутков и островков:

select 
    t.*, 
    sum(case when locationID = lagLocationID then 0 else 1 end) 
        over(partition by personID order by date, time) 
        as transfert_sequence
from (
    select 
        t.*, 
        lag(locationID) 
            over(partition by personID order by date, time) 
            as lagLocationID
    from mytable t
) t

Идея состоит в том, чтобы вычислить сумму окна, которая увеличивается каждый раз при изменении locationID. 1005 * Обратите внимание, что это будет правильно обрабатывать случай, когда человек возвращается в место, где он уже был раньше.

...