Sql 选择大量行并按时间顺序缩放选择的有效方法?
我每隔5分钟将数据插入一个表中,列包含时间戳和数据。我希望根据给定的时间框架选择数据,并适当地省略数据以提高性能和按时间顺序缩放,以便查询返回的最大值为32 例如,我有2周的数据,或4032条记录,每5分钟记录一次。我希望从头到尾进行选择,将结果集减少到32条记录,但记录集按时间顺序排列,以便32条记录中的每个条目在时间上尽可能等距,同时保留集合中的开始记录和结束记录的边缘记录不变 我有一段代码,可以抓取大量的集合,并以计算出的跳过间隔对它们进行迭代,根据需要删除记录并执行边缘检查。我想知道是否有一种在查询中而不是在服务器代码中执行此操作的更快方法。我正在使用MySQL,但我也会接受MsSQL的答案Sql 选择大量行并按时间顺序缩放选择的有效方法?,sql,time,time-series,Sql,Time,Time Series,我每隔5分钟将数据插入一个表中,列包含时间戳和数据。我希望根据给定的时间框架选择数据,并适当地省略数据以提高性能和按时间顺序缩放,以便查询返回的最大值为32 例如,我有2周的数据,或4032条记录,每5分钟记录一次。我希望从头到尾进行选择,将结果集减少到32条记录,但记录集按时间顺序排列,以便32条记录中的每个条目在时间上尽可能等距,同时保留集合中的开始记录和结束记录的边缘记录不变 我有一段代码,可以抓取大量的集合,并以计算出的跳过间隔对它们进行迭代,根据需要删除记录并执行边缘检查。我想知道是否
谢谢。因此,沿着这条线,输入两个日期,5分钟范围和32个样本范围:
SELECT rownum
FROM (SELECT @row := @row +1 AS rownum
,@sampleRate AS sampleRate
FROM (SELECT @row := 0
,@sampleRate := TIMESTAMPDIFF(MINUTE,'2011-12-01 00:00:00','2011-12-15 00:00:00') / 5 / 32 ) r
,clientpc
) ranked
WHERE rownum % @sampleRate = 1
沿着这条线,输入两个日期,5分钟范围和32个样本范围:
SELECT rownum
FROM (SELECT @row := @row +1 AS rownum
,@sampleRate AS sampleRate
FROM (SELECT @row := 0
,@sampleRate := TIMESTAMPDIFF(MINUTE,'2011-12-01 00:00:00','2011-12-15 00:00:00') / 5 / 32 ) r
,clientpc
) ranked
WHERE rownum % @sampleRate = 1
好的,不要说我没有按照上面的评论部分警告你。这是为MSSQL编写的;我对MySQL不熟悉,所以我试着减少uber专有的东西。这可能都可以在一个丑陋的大查询中完成,但这样做会更加难以理解,所以我将其分解为多个步骤 首先,设置一些变量:
DECLARE
@Items real = 32 -- How many items you wish to display
,@From int = 16000 -- Low range delimiter on your target data set
,@Thru int = 17500 -- High range delimiter on your target data set
,@Total real -- Used to store how many items are actually in the target range
简短的测试表明,如果@Items小于2或大于@Total的某个大倍数,那么事情就会失败。需要进行错误处理或输入测试。我使用实数数据类型,以便除法生成十进制值,而不是截断的整数;一定要将这些设置为整数值,否则我不知道会发生什么
下一位创建一个计数表或数字表。它只是一个由升序整数组成的单列表,从1开始,一直到上限。在这里,我把它限制在256,因为32似乎是你的最大值。这个特定的代码非常迟钝,但它可以在令人不安的短时间内生成数百万行,所以每当我需要这样的东西时,我都会剪切粘贴它
CREATE TABLE #Tally (Num int not null)
-- "Table of numbers" data generator, as per Itzik Ben-Gan (from multiple sources)
-- Modified to generate 1 through 256
;WITH
L0 AS (SELECT 1 AS C UNION ALL SELECT 1), --2 rows
L1 AS (SELECT 1 AS C FROM L0 AS A, L0 AS B),--4 rows
L2 AS (SELECT 1 AS C FROM L1 AS A, L1 AS B),--16 rows
L3 AS (SELECT 1 AS C FROM L2 AS A, L2 AS B),--256 rows
num AS (SELECT ROW_NUMBER() OVER(ORDER BY C) AS N FROM L3)
insert #Tally (Num)
select N FROM num
获取目标数据集中的行数:
SELECT @Total = count(*)
from Time
where TimeId between @From and @Thru
查看查询,按排名位置顺序列出目标范围,如集合中的1、2、3、4等。这将处理重复的值。我的测试基于我们的通用时间表,它看起来像任何数据仓库中的大多数时间维度表
SELECT
row_number() over (order by TimeId) Ranking
,TimeId
from Time
where TimeId between @From and @Thru
另一个评论查询。这将返回标识最终集合断点的数字集。例如,如果你有30个项目,想要7个,这将产生{5,10,15,20,25,30};加上1,如果我把问题弄清楚的话,这就是你想要的7
SELECT distinct ceiling((Num - 1) * @Total / (@Items - 1)) from #Tally
这里是包含上述两个查询的工作区。基本上,从第一个查询开始,它的排名/位置与第二个查询中标识的断点相同。我在第一项中加入了一个OR,因为这比试图用数学的方法来填充它要简单得多
SELECT xx.Ranking, xx.TimeId
from (select
row_number() over (order by TimeId) Ranking
,TimeId
from Time
where TimeId between @From and @Thru) xx
where Ranking in (select distinct ceiling((Num - 1) * @Total / (@Items - 1)) from #Tally)
or Ranking = 1
正如我所说的,它过于复杂,可能对某些输入不起作用-但很有可能它的运行速度应该比程序替代方案快。好的,不要说我没有根据上面的评论部分警告您。这是为MSSQL编写的;我对MySQL不熟悉,所以我试着减少uber专有的东西。这可能都可以在一个丑陋的大查询中完成,但这样做会更加难以理解,所以我将其分解为多个步骤 首先,设置一些变量:
DECLARE
@Items real = 32 -- How many items you wish to display
,@From int = 16000 -- Low range delimiter on your target data set
,@Thru int = 17500 -- High range delimiter on your target data set
,@Total real -- Used to store how many items are actually in the target range
简短的测试表明,如果@Items小于2或大于@Total的某个大倍数,那么事情就会失败。需要进行错误处理或输入测试。我使用实数数据类型,以便除法生成十进制值,而不是截断的整数;一定要将这些设置为整数值,否则我不知道会发生什么
下一位创建一个计数表或数字表。它只是一个由升序整数组成的单列表,从1开始,一直到上限。在这里,我把它限制在256,因为32似乎是你的最大值。这个特定的代码非常迟钝,但它可以在令人不安的短时间内生成数百万行,所以每当我需要这样的东西时,我都会剪切粘贴它
CREATE TABLE #Tally (Num int not null)
-- "Table of numbers" data generator, as per Itzik Ben-Gan (from multiple sources)
-- Modified to generate 1 through 256
;WITH
L0 AS (SELECT 1 AS C UNION ALL SELECT 1), --2 rows
L1 AS (SELECT 1 AS C FROM L0 AS A, L0 AS B),--4 rows
L2 AS (SELECT 1 AS C FROM L1 AS A, L1 AS B),--16 rows
L3 AS (SELECT 1 AS C FROM L2 AS A, L2 AS B),--256 rows
num AS (SELECT ROW_NUMBER() OVER(ORDER BY C) AS N FROM L3)
insert #Tally (Num)
select N FROM num
获取目标数据集中的行数:
SELECT @Total = count(*)
from Time
where TimeId between @From and @Thru
查看查询,按排名位置顺序列出目标范围,如集合中的1、2、3、4等。这将处理重复的值。我的测试基于我们的通用时间表,它看起来像任何数据仓库中的大多数时间维度表
SELECT
row_number() over (order by TimeId) Ranking
,TimeId
from Time
where TimeId between @From and @Thru
另一个评论查询。这将返回标识最终集合断点的数字集。对于