Как выбрать эти начальные времена и длительности, если некоторые продолжительности превышают ожидаемые? - PullRequest
0 голосов
/ 22 мая 2019

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

РЕДАКТИРОВАТЬ, но не уменьшилось во времени!

Я выполняю этот запрос на SQL Server 2016. IЯ уже пробовал использовать LEAD и LAG, но не смог заставить его работать правильно.

Исходная таблица

| BeginTime | Duration |
------------------------
| 6:00      |       75 |
| 7:00      |       45 |
| 7:45      |       60 |
| 9:00      |       90 |
| 11:00     |       60 |
| 11:30     |       30 |
------------------------

И вывод должен быть

| BeginTime | Duration |
------------------------
| 6:00      |       75 |
| 7:15      |       45 |
| 8:00      |       60 |
| 9:00      |       90 |
| 11:00     |       60 |
| 12:00     |       30 |
------------------------

Ответы [ 2 ]

2 голосов
/ 22 мая 2019

Вы можете попробовать использовать некоторую агрегатную функцию

  1. LAG оконную функцию с DATEADD
  2. SUM оконной функцией для получения значений Duration.

Тогда только время добавления с total значение столбца берется из подзапроса.

Окончательное время добавления с MIN(BeginTime) среднее время начала.

Запрос1 :

SELECT (CASE WHEN rn = 1 THEN BeginTime
            ELSE DATEADD(MINUTE,LAG(total) OVER(ORDER BY BeginTime),MIN(BeginTime) OVER(ORDER BY BeginTime)) END) BeginTime
      ,Duration
FROM (
  SELECT *,
         SUM(Duration) OVER(ORDER BY BeginTime) total,
         ROW_NUMBER() OVER(ORDER BY BeginTime) rn,
         LAG(BeginTime) OVER(ORDER BY BeginTime) privous
  FROM T
) t1

Результаты :

|        BeginTime | Duration |
|------------------|----------|
| 06:00:00.0000000 |       75 |
| 07:15:00.0000000 |       45 |
| 08:00:00.0000000 |       60 |
| 09:00:00.0000000 |       90 |
1 голос
/ 22 мая 2019
  --Sample
  SELECT CAST('6:00' as TIME) as BeginTime, 75 as Duration
  INTO #Temp  --drop table #Temp
  UNION ALL
  SELECT '7:00',45
  UNION ALL
  SELECT '7:15',45
  UNION ALL
  SELECT '7:45',60
  UNION ALL
  SELECT '8:00',60
  UNION ALL
  SELECT '9:00',90


  --Query starts from here
   DECLARE @MinTime TIME  
  SELECT @MinTime = MIN(BeginTime) FROM #Temp

  DECLARE @MaxTime TIME  
  SELECT @MaxTime = MAX(BeginTime) FROM #Temp
  ;
  WITH A(BeginTime, Duration)
  AS
  (
     SELECT BeginTime, Duration FROM #Temp where BeginTime = @MinTime 
     UNION ALL
     SELECT DATEADD(mi,A.Duration,A.BeginTime),B.Duration
     FROM A 
     INNER JOIN #Temp as B
     ON B.BeginTime = DATEADD(mi,A.Duration,A.BeginTime)
     WHERE DATEADD(mi,A.Duration,A.BeginTime) < = @MaxTime
  )
  SELECT * FROM A

РЕДАКТИРОВАТЬ ОТВЕТ:

В этом случае все остальные BeginTime бесполезны, все, что вам нужно подвести итог - это общее число Duration с самым первым BeginTime:

 SELECT CAST('6:00' as TIME) as BeginTime, 75 as Duration, 1 as [Count]
  INTO #Temp  --drop table #Temp
  UNION ALL
  SELECT '7:00',45, 2
  UNION ALL
  SELECT '8:00',60, 3
  UNION ALL
  SELECT '9:00',90,4
  UNION ALL
  SELECT '10:00',60,5
  UNION ALL
  SELECT '11:00',30,6


DECLARE @MinTime Time
SELECT @MinTime =  MIN(BeginTime) FROM #Temp

SELECT BeginTime,Duration FROM #Temp WHERE BeginTime = @MinTime

UNION ALL

SELECT DATEADD(MI,SUM(B.Duration), @MinTime) as BeginTime,
       A.Duration
FROM #Temp as A
INNER JOIN #Temp as B
ON B.[Count] < A.[Count]
WHERE A.BeginTime != @MinTime
GROUP BY A.Duration, A.[Count]
ORDER BY BeginTime
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...