SQL按时间分组
我有一个表,它有一个我想要分组的列,但是只有它的最后一个系列,表有一个时间戳列,例如表SQL按时间分组,sql,sql-server-express,Sql,Sql Server Express,我有一个表,它有一个我想要分组的列,但是只有它的最后一个系列,表有一个时间戳列,例如表 Type | Time ============= A | 1:00 A | 1:05 B | 1:10 C | 1:15 A | 1:20 A | 1:25 A | 1:30 我想对这些函数进行分组,以便在其上执行Sum、Max、Avg,在分组被破坏之前只获取该组,因此标准的按类型分组将不起作用 我想要一些像: Type | count_in_series | M
Type | Time
=============
A | 1:00
A | 1:05
B | 1:10
C | 1:15
A | 1:20
A | 1:25
A | 1:30
我想对这些函数进行分组,以便在其上执行Sum、Max、Avg,在分组被破坏之前只获取该组,因此标准的按类型分组将不起作用
我想要一些像:
Type | count_in_series | MinTime
================================
A | 2 | 1:00
B | 1 | 1:10
C | 1 | 1:15
A | 3 | 1:20
没有办法知道什么时候会发生变化,给出的数据只是一个例子来说明这一点
这可能吗
解决方案
我使用了下面答案中的概念。结果证明我使用的程序不允许变量或CTE。下面是我使用子查询的解决方案:
SELECT
Type
, max(t_stamp) as maxTime
, min(t_stamp) as minTime
FROM
(SELECT
*
, ROW_NUMBER() OVER (ORDER BY t_stamp desc) - ROW_NUMBER() OVER (PARTITION BY Type ORDER BY t_stamp desc) as grouping
FROM MyTable) as t1
GROUP BY t1.grouping, t1.Type
ORDER BY min(t_stamp) desc
像这样的方法应该会奏效:
SELECT
Type,
count('Type'),
min('Time')
FROM table
GROUP BY Type
---编辑----
如果可以使用用户变量,则可以:
SET @typeIndex = 1;
SELECT
min(type) as type,
count(type) as count,
min(TIME_FORMAT(time, '%H %i')) as minTime
FROM(
SELECT
t.type,
t.time,
(SELECT type FROM timeTest tt
WHERE tt.time < t.time
ORDER BY time DESC LIMIT 1) as next_type,
IF(type != (SELECT type FROM timeTest tt
WHERE tt.time < t.time
ORDER BY time DESC LIMIT 1), @typeIndex := @typeIndex+1, "" ) as t ,
@typeIndex as tipeIndex
FROM
timeTest t
) temp
GROUP BY temp.tipeIndex
您可以使用lag和row_编号来获得正确的存储桶,然后按以下方式进行分组:
;with cte as (
select *, Bucket = sum(sm) over (order by RowN) from (
select *,sm = case when (lag(type,1) over (order by [time]) <> [type]) then 1 else 0 end,
RowN= row_number() over(order by [time]) from #yourtime
) a
)
select min([Type]) as [Type], count([Type]) as Count_in_Series, min([time]) as MinTime from cte
group by Bucket
您的输入表:
create table #yourtime (type varchar(2), [Time] time)
insert into #yourtime ([type], [time]) values
('A','1:00')
,('A','1:05')
,('B','1:10')
,('C','1:15')
,('A','1:20')
,('A','1:25')
,('A','1:30')
如果你没有延迟,你可以只使用行号
输出
您使用的是哪种数据库管理系统?SQL Server?如果引擎支持,Oracle?窗口功能主管可能会帮助您。如果不是,您可以使用用户变量并分配行号,然后在row_number+1=rowNumber上联接,然后将T1.Type与T2.Type进行比较。相同时键入,不同时添加计数。@GurwinderSingh SQL express通过点火客户端不完全:查看预期结果中的2 a。基本上计数,直到类型更改,然后重置计数。并显示每个组的最小时间。我使用的客户端不允许变量或CTE,但我提出了一个使用子查询的解决方案。谢谢,请参阅我的问题编辑,了解我使用的解决方案为什么您没有在[时间]之前使用过order?我喜欢按照输入顺序将其存储在表中,因为我们要求lagdb表的顺序是无序数据集,除非您包括order by,例如,索引和分区可以提供不同的结果,因为数据存储方式不同..是的,我知道。。这里的要求是保持第一个桶中的前两个A的顺序,然后是B、C和第四个桶中的下一个3 A的顺序,然后我们只能相应地进行最小和最大。。。如果我按时间下单,那么我们将失去这个订单,在实际场景中,他可能在那个专栏上有一个合适的订单,如果你按时间下单,你将获得OP所需的订单。前两个A,后三个A。现在你的答案是不确定的。因为可以根据db存储这些行的方式提供不同的结果。在OP没有提供订单的情况下,您应该要求提供订单。我使用的客户端不允许变量或CTE,但使用您的概念,我提出了使用子查询的解决方案。谢谢,请参见我使用的解决方案的问题编辑
create table #yourtime (type varchar(2), [Time] time)
insert into #yourtime ([type], [time]) values
('A','1:00')
,('A','1:05')
,('B','1:10')
,('C','1:15')
,('A','1:20')
,('A','1:25')
,('A','1:30')
With CTE AS (
SELECT T.*,
ROW_NUMBER() OVER (ORDER BY [TIME]) as ID,
ROW_NUMBER() OVER (PARTITION BY [Type] ORDER BY [TIME]) as rn
FROM Table1 T
)
SELECT [Type], COUNT(*) Count , MIN(Time) Time
FROM CTE
GROUP BY [Type], ID - rn
ORDER BY MIN(Time)