【问题标题】:SQL Server : how to select a fixed amount of rows (select every x-th value)SQL Server:如何选择固定数量的行(选择每个 x-th 值)
【发布时间】:2012-04-04 08:26:56
【问题描述】:

简短描述:我有一个表格,其中包含在特定时间段内更新的数据。现在的问题是,根据发送数据的传感器的性质,在这段时间内可能有 50 个数据集或 50.000 个数据集。由于我想可视化这些数据(使用 ASP.NET / c#),因此对于第一次预览,我想从表中仅选择 1000 个值。

我已经有了这样做的方法:我计算感兴趣时间段内的行数,用一个简单的“where”子句指定传感器 ID,将其保存为 SQL 中的变量,然后除以计数( ) 到 1000。我已经在 MS Access 中尝试过,它工作得很好:

set @divider = select count(*) from table where [...]

SELECT (Int([RowNumber]/@divider)), First(Value)
FROM myTable
GROUP BY (Int([RowNumber]/@divider));

Access 的诀窍在于,我只有一个数据字段(“RowNumber”),这是我的 PK/ID,从 0 开始。我尝试在 SQL Server 中使用ROW_NUMBER() 方法来实现这一点,该方法或多或少都有效。我有该方法的正确语法,但我不能使用GROUP BY 语句

窗口函数只能出现在 SELECT 或 ORDER BY 条款。

意思是ROW_NUMBER()不能出现在GROUP BY语句中。

现在我有点卡住了。我试图将ROW_NUMBER 值保存到一个字符或单独的列中,稍后再保存GROUP BY,但我无法完成。不知何故,我开始认为,我的策略可能有其弱点......? :/

再次澄清:我不需要从我的表中SELECT TOP 1000,因为这只是意味着我选择了前 1000 个值(取决于排序)。我需要 SELECT 每个 x-th 值,同时我可以计算 x(如果这有助于完成它,我什至可以将它四舍五入为 INT)。我希望我能够描述可以理解的问题...

这是我在 StackOverflow 上的第一篇文章,我希望我没有忘记任何重要或重要的信息,如果您需要任何进一步的信息(表结构、我目前的查询......)请不要犹豫.任何帮助或提示都非常感谢 - 在此先感谢! :)


更新:解决方案!非常感谢https://stackoverflow.com/users/52598/lieven!!!

这是我最后的做法:

我声明了 2 个变量 - 我计算我的行数并将其设置到第一个变量中。然后我在刚刚分配的变量上使用 ROUND(),并将它除以 1000(因为最后我想要大约 1000 个值!)。我将此操作拆分为 2 个变量,因为如果我使用 COUNT 函数的值作为我的 ROUND 操作的基础,则会出现一些错误。

declare @myvar decimal(10,2) 
declare @myvar2 decimal(10,2)

set @myvar = (select COUNT(*)
from value_table
where channelid=135 and myDate >= '2011-01-14 22:00:00.000' and myDate <= '2011-02-14 22:00:00.000'
)

设置@myvar2 = ROUND(@myvar/1000, 0)

现在我有了一个四舍五入的值,我想将它作为我的步长(取每个第 x 个值 -> 这是我们的“x”;))存储在 @myvar2 中。接下来,我将选择所需时间跨度和通道的数据,并将 ROW_NUMBER() 添加为列“rn”,最后在外部 SELECT 中添加一个 WHERE 子句,其中我将 ROW_NUMBER 通过@myvar2 划分 - 当模数为0,该行将被选中。

select * from
(
select (ROW_NUMBER() over (order by id desc)) as rn, myValue, myDate
from value_table
where channel_id=135 and myDate >= '2011-01-14 22:00:00.000' and myDate<= '2011-02-14 22:00:00.000'
) d
WHERE rn % @myvar2 = 0

像魅力一样工作 - 再次感谢https://stackoverflow.com/users/52598/lieven,请参阅下面的评论以获取原始帖子!

【问题讨论】:

  • 您能否提供一些简化的数据示例和所需的输出?
  • 您能提供您使用的 SQL 版本吗?它似乎是 mySQL,但在 2005 年、2008 年等?
  • @Sparky - 实际上,他确实在这个问题上说 MS SQL,所以是 SQL Server,对于 ROW_NUMBER 的使用,它应该是 2005+
  • 欢迎您!提供带有虚拟数据和所需输出的表结构示例以及明确说明您正在使用的 RDBMS(MySQL、SQL Server 等)和版本(2005、2008 等)始终是一个好主意.
  • 大家好,我使用 MS SQL 2008 (10.0.5500),我的表非常简单:ID(PK,INT) / Value(float) / Date(DateTime) / SensorID(FK, INT)所以 ID 只是我的值表的 PK,不能用于识别我的条目。值是真正感兴趣的字段,而日期是 - 自我解释 - 值条目的时间戳。

标签: sql sql-server sql-server-2008 select


【解决方案1】:

本质上,选择第 x 个值所需要做的就是保留行数除以 x 的模数为 0 的所有行。

WHERE rn % @x_thValues = 0

现在为了能够使用您的 ROW_NUMBER 的结果,您需要将整个语句包装到一个子选择中

SELECT  *
FROM    (
            SELECT  *
                    , rn = ROW_NUMBER() OVER (ORDER BY Value)
            FROM    DummyData
        ) d
WHERE   rn % @x_thValues = 0                    

结合你需要的 x-th 值的变量,你可以使用类似这个 testscript 的东西

DECLARE @x_thValues INTEGER = 2

;WITH DummyData AS (SELECT * FROM (VALUES (1), (2), (3), (4)) v (Value))
SELECT  *
FROM    (
            SELECT  *
                    , rn = ROW_NUMBER() OVER (ORDER BY Value)
            FROM    DummyData
        ) d
WHERE   rn % @x_thValues = 0                    

【讨论】:

  • 这是使用窗口函数的标准做法。内部查询获取结果,外部查询进行过滤。
  • 您好,感谢您的快速回复,明天我会试一试,并立即通知您 - 看起来很有希望! :)
  • 像魅力一样工作 - 使用 WHERE 子句中的模数是解决方案。非常感谢!
【解决方案2】:

要考虑的另一个选项:

Select Top 1000 * 
From dbo.SomeTable 
Where ....
Order By NewID()

但老实说 - 比这个更喜欢上一个答案。 问题可能与性能有关..

【讨论】:

  • @Janis - 这个问题是第 1000 个随机记录被选中。我不认为那是OP的意图。需要对结果集进行排序,并从该有序集中选择第 n 个值。
猜你喜欢
  • 2012-09-24
  • 1970-01-01
  • 1970-01-01
  • 2010-11-29
  • 2019-04-30
  • 2020-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多