每当另一个字段值为零时,返回字段的最大值

时间:2015-11-24 09:38:02

标签: sql-server

我有一个像这样的表结构:

 name     idletime     speed

 RJ14       300           0
 RJ14       360           0
 RJ14       400           0
 RJ14        0            30
 RJ14        50           0
 VJ23       100           0
 VJ23       160           0
 VJ23       200           0
 VJ23        0            50
 VJ23        30           0

 

我想要这种格式的结果

 name     idletime

 RJ14       400      
 RJ14        50      
 VJ23       200      
 VJ23        30      

 

我需要一个查询,只要另一个字段(速度)的值为零,就可以返回字段的最大值。有什么建议?感谢。

修改

当特定名称的速度大于零时,idletime变为零。我需要在每次变为零之前的空闲时间值。

我已经尝试过此查询,但它没有返回预期的结果。

  SELECT NAME ,MAX(idleTime) FROM idletime WHERE speed=0 GROUP BY NAME

3 个答案:

答案 0 :(得分:3)

  

当特定speed的{​​{1}}大于零时,name变为零。我需要idletime的值,然后每次都变为零。

     
    

每一行都有唯一的ID

  

<强>查询

idletime

<强> SQL fiddle

工作原理

  1. 首先,我们创建一个添加;WITH numberedidletable AS ( SELECT id,name,idletime,speed, ROW_NUMBER() OVER (ORDER BY name,id) AS RN FROM idletable ) SELECT name,idletime FROM numberedidletable WHERE speed = 0 AND RN IN ( (SELECT RN-1 FROM numberedidletable tmpnit WHERE speed<>0 AND numberedidletable.name = tmpnit.name) UNION ALL (SELECT MAX(RN) FROM numberedidletable GROUP BY name) ) ORDER BY RN 的表格(因为我们无法保证唯一ID是顺序的):

    ROW_NUMBER()
  2. 然后,我们得到行号(;WITH numberedidletable AS ( SELECT id,name,idletime,speed, ROW_NUMBER() OVER (ORDER BY name,id) AS RN FROM idletable ) ),其中下一行有RN

    speed <> 0
  3. 并且,每个 (SELECT RN-1 FROM numberedidletable tmpnit WHERE speed<>0 AND numberedidletable.name = tmpnit.name) 的最后一项的所有行号:

    name
  4. 最后选择这些行号的所需列:

            UNION ALL
                (SELECT MAX(RN)
                  FROM numberedidletable
                  GROUP BY name)
    
  5. <强>假设

    • SELECT name,idletime FROM numberedidletable WHERE speed = 0 AND RN IN ( ... ) ORDER BY RN 是每个部分的增量。
    • idletime是唯一ID

    <强>输出

    id

    <强> SQL fiddle

答案 1 :(得分:2)

那么你想要所有按ID排序的最大空闲记录以及之后没有非空闲记录的所有记录吗?

这比我想象的要复杂得多。您可以使用多个CTE来简化它:

WITH CTE AS
(
    SELECT ID, Name, IdleTime, Speed,
           RN = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY ID ASC)
    FROM dbo.TableName t
)
, Idles AS
(
    SELECT ID, Name, IdleTime, Speed, RN 
    FROM CTE
    WHERE Speed = 0 AND IdleTime <> 0
)
, NonIdles AS
(
    SELECT ID, Name, IdleTime, Speed, RN
    FROM CTE
    WHERE Speed <> 0 AND IdleTime = 0
)
SELECT ID, Name, IdleTime, Speed
FROM Idles i
WHERE NOT EXISTS
(
    SELECT 1 FROM Idles i2
    WHERE  i.Name = i2.Name AND i2.RN > i.RN
)
OR EXISTS
(
    SELECT 1 FROM NonIdles ni
    WHERE  i.Name = ni.Name AND i.RN + 1 = ni.RN 
)
带有示例数据的

SQL-Fiddle

答案 2 :(得分:2)

我为此问题尝试了一种程序化方法。它为我解决了。下面的查询选择速度= 0时的最大空闲时间和速度从非零值再次变为0的第一个空闲时间值。

 Create table stack (id varchar(5), id1 int, id2 int)
 INSERT INTO STACK
 VALUES

 ('RJ14'  ,     300     ,      0     ),
 ('RJ14'  ,     360     ,      0     ),
 ('RJ14'  ,     400     ,      0     ),
 ('RJ14'  ,      0      ,      30    ),
 ('RJ14'  ,     50      ,      0     ),
 ('VJ23'  ,     100     ,      0     ),
 ('VJ23'  ,     160     ,      0     ),
 ('VJ23'  ,     200     ,      0     ),
 ('VJ23'  ,      0      ,      50    ),
 ('VJ23'  ,      30     ,      0     )

 declare @stack as table (name varchar(5),idletime int, id2 int, rws int)
 declare @val   as table (name varchar(5),idletime int )

 insert into @stack
 SELECT ID,ID1 idletime, id2, row_number() over(order by id ) as rws
 FROM STACK

 declare @id    int = 1
 declare @count int 
 declare @value int = 0

 select @count = count (*) from @stack

 while (@id <= @count)
 begin

     select @value = ID2 from @stack where rws = @id and id2 <> 0
     if @value <> 0
     begin
         insert into @val
         select name, idletime 
         from @stack
         where rws = @id -1
         union
         select name, idletime from
         @stack where rws = @id + 1
      end  
         select @id    = @id + 1
         select @value = 0
  end

  select *from @val ORDER BY NAME, idletime DESC

这是相同的SQL-FIDDLE

sqlfiddle