SQL查询求和列,直到满足行条件,然后继续求和列

SQL查询求和列,直到满足行条件,然后继续求和列,sql,sql-server,sum,Sql,Sql Server,Sum,数据: SQL Server 2012-我需要扫描如上所示的表格,并对duration列进行汇总,直到Paycode列中的行出现中断 然后继续汇总中断行后的持续时间列 i、 我想得到的结果 Sum of Duration --------------- 6.08 3.33 我尝试了此语句,但它没有返回上述预期结果: SELECT duration, paycode, visitstart INTO #client FROM VISITS WHERE visitstart > '2020-

数据:

SQL Server 2012-我需要扫描如上所示的表格,并对duration列进行汇总,直到Paycode列中的行出现中断

然后继续汇总中断行后的持续时间列

i、 我想得到的结果

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

请告知

尝试下面的方法-这是一个缺口和孤岛问题


试试下面的一个——这是一个缺口和孤岛问题


您可以通过对中断出现的次数求和来分配组。然后你可以聚合。我不太确定最终的持续时间是如何定义的,尤其是是否包括中断行。假设是:

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

您可以通过对中断出现的次数求和来分配组。然后你可以聚合。我不太确定最终的持续时间是如何定义的,尤其是是否包括中断行。假设是:

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

史蒂夫C,我试着帮你。。。 我做了几次cte

cte cteBreak-您只需选择中断。 cte断开\u链-对每个断开进行编号,因为无法使用行编号 断链-通过成对获得断链间隔,例如 第一次突破-第二次突破, 时间第二次休息时间第三次休息 注意:若它是最后一个间隔,则列end_break将替换为getdate,以关闭间隔

最后我们把我们的桌子和链子结合起来 而不是表键入您的表名

--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

另外,如果你有问题,请写在评论中。所以,史蒂夫C,我试着帮你。。。 我做了几次cte

cte cteBreak-您只需选择中断。 cte断开\u链-对每个断开进行编号,因为无法使用行编号 断链-通过成对获得断链间隔,例如 第一次突破-第二次突破, 时间第二次休息时间第三次休息 注意:若它是最后一个间隔,则列end_break将替换为getdate,以关闭间隔

最后我们把我们的桌子和链子结合起来 而不是表键入您的表名

--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


注意:如果您有问题,请在评论中写出来。请以表格形式提供您的预期输出。如果您设置了db/sql FIDLE,或者至少将问题中的数据作为文本或DDL语句,也会有所帮助。图像没有用处。我的歉意刚刚通过SQL server 2008 SP3-GDR实现,选择sumduration作为选择访问的总持续时间。*,按访问开始的订单上的行数作为seqnum,当paycode='BREAK'时,分区上的行号为1,其他为0,visitstart结束订单,作为seqnumt,从paycode'BREAK'和EMP_ID='S0000000182'的访问访问,visitstart>'2020-01-20'和visitstart<'2020-01-21'按seqnum分组,seqnumt@SteveC。为什么要使用不受支持的商业产品版本?Steve C,我专门为Sql server 2008编写了查询…您是否尝试我的查询?以表格格式提供您的预期输出如果您设置了db/Sql FIDLE,或者至少将数据作为文本或DDL语句放在问题中,这也会有所帮助。图像没有用处。我的歉意刚刚通过SQL server 2008 SP3-GDR实现,选择sumduration作为选择访问的总持续时间。*,按访问开始的订单上的行数作为seqnum,当paycode='BREAK'时,分区上的行号为1,其他为0,visitstart结束订单,作为seqnumt,从paycode'BREAK'和EMP_ID='S0000000182'的访问访问,visitstart>'2020-01-20'和visitstart<'2020-01-21'按seqnum分组,seqnumt@SteveC。为什么您使用的是不受支持的商业产品版本?Steve C,我专门为Sql server 2008编写了查询…您是否尝试过我的查询?您能否详细解释paycode='Break'然后1或0的情况?我花了更多的时间来弄清楚。我想这会让很多像我这样的SQL初学者感到困惑@劉鎮瑲, 它用于根据您的薪资代码创建一个组。它是指按Break分组还是将每个薪资代码分组在一起@劉鎮瑲, 是的,就是这样。我的道歉刚刚通过SQL server 2008 SP3-GDR实现,选择sumduration作为选择访问的总持续时间。*,按访问开始的订单上的行数作为seqnum,当paycode='BREAK'时,按案例划分的行数,然后按seqnum按visitstart结束订单。当paycode'BREAK'和EMP_ID='S0000000182'和visitstart>'2020-01-20'和visitstart<'2020-01-21'按seqnum分组时,seqnum您能解释更多关于paycode='BREAK'然后按seqnum分组的情况吗?我花了更多的时间来弄清楚。我想这会让很多像我这样的SQL初学者感到困惑@劉鎮瑲, 它用于根据您的薪资代码创建一个组。它是指按Break分组还是将每个薪资代码分组在一起@劉鎮瑲, 是的,就是这样,我的道歉刚刚通过SQL server 2008 SP3-GDR实现,选择sumduration作为选择访问的总持续时间。*,按访问顺序的行数开始作为seqnum,当paycode='BREAK时,按情况划分的行数