我有一个数据集,我需要在其中找到用户休息时登录的“班级”。中断的“类”应与中断之前的第一个登录事件的“类”相同。 很高兴将数据放在额外的列中,只是不确定如何处理。
---------------------------------------
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)每次都陷入死胡同。
答案 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
说明
答案 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函数的新列。