sql—计算分区上的值更改时的运行总数

qxsslcnc  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(309)

我很难想出如何写一个窗口函数来解决我的问题。我是窗口函数的新手,但我认为可以编写一个来满足我的需要。
问题陈述:
我想计算一个传输序列,显示一个人何时根据相应的位置id改变了位置。
样本数据(表1)

  1. +----------+------------+-----------+---------+
  2. | PersonID | LocationID | Date | Time |
  3. +----------+------------+-----------+---------+
  4. | 12 | A | 6/17/2020 | 12:00PM |
  5. +----------+------------+-----------+---------+
  6. | 12 | A | 6/18/2020 | 1:00PM |
  7. +----------+------------+-----------+---------+
  8. | 12 | B | 6/18/2020 | 6:00AM |
  9. +----------+------------+-----------+---------+
  10. | 12 | C | 6/19/2020 | 3:00PM |
  11. +----------+------------+-----------+---------+
  12. | 13 | A | 6/16/2020 | 8:00AM |
  13. +----------+------------+-----------+---------+
  14. | 13 | A | 6/16/2020 | 11:00AM |
  15. +----------+------------+-----------+---------+
  16. | 13 | A | 6/16/2020 | 12:00AM |
  17. +----------+------------+-----------+---------+
  18. | 13 | B | 6/16/2020 | 4:00PM |
  19. +----------+------------+-----------+---------+

预期结果

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

我试过的

  1. SELECT
  2. [t1].[PersonID]
  3. ,[t1].[LocationID]
  4. ,[t1].[Date]
  5. ,[t1].[Time]
  6. ,DENSE_RANK()
  7. OVER(
  8. partition BY [t1].[PersonID], [t1].[LocationID]
  9. ORDER BY [t1].[Date] ASC, [t1].[Time] ASC) AS
  10. [Transfer Sequence]
  11. FROM Table1 [t1]

不幸的是,我认为无论locationid的值是否改变,都是在分配一个秩。我需要一个函数,将只添加一个序列时,locationid已经改变。
任何帮助都将不胜感激。
谢谢您!

s3fp2yjn

s3fp2yjn1#

您希望将“相邻”行放在同一组中。straigt窗口函数不能为您做到这一点-我们需要使用间隙和孤岛技术:

  1. select
  2. t.*,
  3. sum(case when locationID = lagLocationID then 0 else 1 end)
  4. over(partition by personID order by date, time)
  5. as transfert_sequence
  6. from (
  7. select
  8. t.*,
  9. lag(locationID)
  10. over(partition by personID order by date, time)
  11. as lagLocationID
  12. from mytable t
  13. ) t

其思想是计算一个窗口和,每次locationid改变时它都会递增。
请注意,当一个人回到他们以前去过的地方时,这将正确地处理这个情况。

展开查看全部
xa9qqrwz

xa9qqrwz2#

我所做的(我相信这不是最好的方法)是为传输序列(sequence)创建第二个表,其中包含personid、locationid、date、time和空字段,然后是一个游标:

  1. DECLARE transaction CURSOR
  2. FOR select PersonID, LocationID, Date, Time from table1;

然后循环:

  1. OPEN CURSOR transaction
  2. set @count = 0
  3. set @person_saved = ""
  4. set @location_saed = ""
  5. FETCH NEXT FROM transaction INTO @person, @location, @date, @time
  6. WHILE @@FETCH_STATUS = 0
  7. BEGIN
  8. if @person_saved <> @person -- changing personID, reset count
  9. begin
  10. set count = 0
  11. set persone_saved = @person
  12. end
  13. if @location_saved <> @location. -- changing location, add count
  14. begin
  15. set @count = @count + 1
  16. set @location_saved = @location
  17. end
  18. update table1 set sequence = @count where PersonId = @person and locationId = @location and date = @date and time = @time
  19. FETCH NEXT FROM transaction INTO @person, @location, @date, @time
  20. END
  21. CLOSE transaction
  22. DEALLOCATE transaction
展开查看全部

相关问题