SQL столбец суммы запроса, пока не будет выполнено условие строки, и столбец суммы продолжения - PullRequest
1 голос
/ 07 августа 2020

Данные:

введите описание изображения здесь

SQL Server 2012 - мне нужно «просканировать» таблицу, как показано выше, и просуммировать столбец продолжительности до строки с «BREAK» в столбце Paycode.

Затем продолжайте суммировать столбец продолжительности после строки «BREAK»

, т.е. я хочу получить результаты

Sum of Duration
---------------
6.08
3.33

Я пробовал этот оператор, но он не возвращает желаемый результат выше:

SELECT duration, paycode, visitstart
INTO #client
FROM VISITS
WHERE visitstart > '2020-01-20'
  AND visitstart < '2020-01-21'
  AND paycode <> 'BREAK'
ORDER BY VISITSTART, CLIENT_ID

SELECT SUM(duration) AS total_duration, visitstart, paycode
FROM #client
GROUP BY visitstart, paycode

DROP TABLE #client

Пожалуйста, сообщите

Ответы [ 3 ]

2 голосов
/ 07 августа 2020

Попробуйте следующее - это gap & island проблема

select sum(duration) as total_duration
from
(
select t.*,
       row_number() over (order by visitstart) as seqnum,
       row_number() over (partition by case when paycode='Break' then 1 else 0 end order by visitstart) as seqnumt
from yourtablename t
)A 
where paycode<>'Break'
group by (seqnum-seqnumt)
1 голос
/ 07 августа 2020

Вы можете назначать группы, суммируя количество раз, которое появляется "BREAK". Затем вы можете агрегировать. Я не совсем уверен, как определяется окончательная продолжительность - в частности, включена ли строка «BREAK». Предполагая, что это:

select min(visitstart), max(visitstart),
       sum(duration)
from (select t.*,
             sum(case when paycode = 'BREAK' then 1 else 0 end) over (order by visitstart) as grp
      from t
     ) t
where paycode <> 'BREAK'
group by grp
0 голосов
/ 08 августа 2020

Итак, Стив C, я попытался вам помочь ... Я сделал несколько cte

  1. cte (cteBreak) - вы просто выбираете только перерывы.
  2. cte (breaks_chains) - нумерация каждого перерыва (поскольку нельзя использовать row_numbing)
  3. breaks_chains - получить интервалы перерывов по парам (например, время первого перерыва - время второго перерыва, время второго перерыва, время третьего перерыва)

Примечание: если это последний интервал, то столбец end_break заменяется getdate (), просто для закрытия интервала

и наконец объединяем нашу таблицу с breaks_chains Вместо Table введите свое Имя таблицы

--just get rows with BREAK paycode
 with cteBreak as
  (
    select * from Table where paycode='BREAK'
  ),

 --numbering breaks (=row_numbering() in later version sql server)
 breaks_chains as
 (
  select cte1.visitstart visit_st,count(cte2.visitstart)+1 Num from cteBreak cte1
  left join cteBreak cte2
  on cte1.visitstart>cte2.visitstart
  group by cte1.visitstart
 ),

 --get pairs as "start_break - end_break"
 break_interval as
 (
  select t1.visit_st begin_break, COALESCE(t2.visit_st,getdate()) as end_break,t1.Num from 
  breaks_chains t1
  left join breaks_chains t2
  on t2.Num-t1.Num=1
 )


 select sum(duration) from
 (
 select duration,paycode,
  case
     when 
        (Table.visitstart>break_interval.begin_break
         and Table.visitstart<break_interval.end_break)
     then break_interval.end_break    

     when (Table.visitstart<break_interval.begin_break and Num=1)
     then  break_interval.begin_break
 end NumGroup
 from Table
 left join break_interval
 on 
   (Table.visitstart>break_interval.begin_break  
   and Table.visitstart<break_interval.end_break)
 or 
   (Table.visitstart<break_interval.begin_break and Num=1) --for first sequence (before first break)
 )t
 where paycode<>'BREAK'
 group by NumGroup

PS Если есть вопросы, напишите в комментариях)

...