SQL-检索数据,其中最大数字<数字

时间:2019-04-26 02:53:55

标签: sql sql-server

我有一个数据集,我需要在其中找到用户休息时登录的“班级”。中断的“类”应与中断之前的第一个登录事件的“类”相同。 很高兴将数据放在额外的列中,只是不确定如何处理。

---------------------------------------
CREATE TABLE Test (     
       [Rowid] INT NOT NULL
      ,[Agent_Name] VARCHAR NOT NULL
      ,[Type Login_Break] VARCHAR NOT NULL
      ,[Class] INT NOT NULL
  PRIMARY KEY (Rowid)
);

INSERT INTO Test 
    ([Rowid], [Agent_Name], [Type Login_Break],[Class]) 
VALUES 
    (7276541,'TrevorT','Login',162),
    (7276993,'TrevorT','Break',0),
    (7277421,'TrevorT','Break',0),
    (7278660,'TrevorT','Login',106),
    (7278754,'TrevorT','Login',162),
    (7279485,'TrevorT','Break',0),
    (7280372,'TrevorT','Login',69),
    (7280984,'TrevorT','Break',0),
    (7281135,'TrevorT','Login',162),
    (7282310,'TrevorT','Login',162),
    (7283716,'TrevorT','Break',0)
---------------------------------------------

我最初的想法是尝试CTE,其中MAX(RowID)<(RowID)每次都陷入死胡同。

原始输出:

enter image description here

必需的输出:

enter image description here

5 个答案:

答案 0 :(得分:3)

啊,您可以尝试这样的事情:

with data as (
    select *, 
        case 
        when class = 0 then
          (
            select max(rowid) from test
            where class > 0 and rowid < a.rowid
          )
        else null
        end as newrowid
    from test a
)
select
    data.rowid, data.agent_name, data.[type login_break],
    case when data.class = 0 then test.class else data.class end as class
from data
left join test on data.newrowid = test.rowid;

结果

rowid   agent_name  type login_break    class
7276541 TrevorT     Login               162
7276993 TrevorT     Break               162
7277421 TrevorT     Break               162
7278660 TrevorT     Login               106
7278754 TrevorT     Login               162
7279485 TrevorT     Break               162
7280372 TrevorT     Login               69
7280984 TrevorT     Break               69
7281135 TrevorT     Login               162
7282310 TrevorT     Login               162
7283716 TrevorT     Break               162

示例:https://rextester.com/QITJ76405

说明

  • 使用测试创建虚拟数据集
  • 在此虚拟数据集中,为class = 0添加一列
  • 此列将是前几行的最大ID
  • 这样,您将在休息前获得有关上一课的信息
  • 从该虚拟数据集中获取所有数据,并将其与newrowid与原始rowid匹配的原始数据结合起来
  • 当虚拟数据集的类别为0时,将其替换为原始类别中的类

答案 1 :(得分:2)

这将在SQL Server上运行,使用的语法是SQL标准

SQL Server提琴:https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=9733051365513941f5057dc38c0b6356

Postgres小提琴:https://www.db-fiddle.com/f/uxVcYPsw4tFCjpJtX3VrCh/0

with a as 
(
  select
      *, 
      sum(case when type_login_break = 'Login' then 1 end) 
      over(order by row_id) as login_group
  from test
)
select 
    row_id, agent_name, type_login_break, 
    class, 
    sum(class) over(partition by login_group order by row_id)
from a;

输出:

| row_id  | agent_name | type_login_break | class | sum |
| ------- | ---------- | ---------------- | ----- | --- |
| 7276541 | TrevorT    | Login            | 162   | 162 |
| 7276993 | TrevorT    | Break            | 0     | 162 |
| 7277421 | TrevorT    | Break            | 0     | 162 |
| 7278660 | TrevorT    | Login            | 106   | 106 |
| 7278754 | TrevorT    | Login            | 162   | 162 |
| 7279485 | TrevorT    | Break            | 0     | 162 |
| 7280372 | TrevorT    | Login            | 69    | 69  |
| 7280984 | TrevorT    | Break            | 0     | 69  |
| 7281135 | TrevorT    | Login            | 162   | 162 |
| 7282310 | TrevorT    | Login            | 162   | 162 |
| 7283716 | TrevorT    | Break            | 0     | 162 |

答案 2 :(得分:2)

如果SQL Server具有user-defined aggregate,则可以一次性通过:

实时测试:https://www.db-fiddle.com/f/vXymxPPj3Ngmqoa9DqFc7S/0

select *, 
    sum_with_reset(class, type_login_break = 'Login') over(order by row_id)
from test

输出:

| row_id  | agent_name | type_login_break | class | sum_with_reset |
| ------- | ---------- | ---------------- | ----- | -------------- |
| 7276541 | TrevorT    | Login            | 162   | 162            |
| 7276993 | TrevorT    | Break            | 0     | 162            |
| 7277421 | TrevorT    | Break            | 0     | 162            |
| 7278660 | TrevorT    | Login            | 106   | 106            |
| 7278754 | TrevorT    | Login            | 162   | 162            |
| 7279485 | TrevorT    | Break            | 0     | 162            |
| 7280372 | TrevorT    | Login            | 69    | 69             |
| 7280984 | TrevorT    | Break            | 0     | 69             |
| 7281135 | TrevorT    | Login            | 162   | 162            |
| 7282310 | TrevorT    | Login            | 162   | 162            |
| 7283716 | TrevorT    | Break            | 0     | 162            |

sum_with_reset定义:

create or replace function sum_reset_accum(
    _accumulated numeric, _current numeric, reset boolean
)
returns numeric as
$$
    select case when reset then
        _current
    else
        _current + _accumulated
    end    
$$ language sql;


create aggregate sum_with_reset(numeric, boolean)
(
    sfunc = sum_reset_accum,
    stype = numeric,
    initcond = 0
);

答案 3 :(得分:0)

无需CTE或等级,只需使用case语句进行简单选择:

 select  
         Rowid, 
         agent_name, 
case [type login_break] when 'login' then RowID else
         (select top 1 RowID from test where RowID < t.Rowid and BreakClass='Break' order by 
         rowid desc) end as Login_Break_Class
    from test t 

答案 4 :(得分:0)

没有完整的表模式会有点困难,但是我建议使用RANK()或DENSE_RANK()函数创建CTE。然后是这样的:

SELECT * FROM cte1 WHERE R = 1; 

其中R =使用Rank函数的新列。