2012-03-19 61 views
4

简短说明:我有一个数据表在某个时间段内更新。现在的问题是 - 根据发送数据的传感器的性质 - 在此时间段内可能有50个数据集或50,000个数据集。因为我想要可视化这些数据(使用ASP.NET/c#),所以对于第一次预览,我希望从表中只选择1000个值。SQL Server:如何选择固定数量的行(每x次选择一个值)

我已经有这样做的方法:我在感兴趣的时间段内对行进行计数,用一个简单的“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开始。我尝试使用ROW_NUMBER()方法在SQL Server中完成该操作,该方法或多或少地起作用。我已经得到了该方法的正确的语法,但我不能使用GROUP BY声明

窗函数只能出现在SELECT或ORDER BY子句 。

含义ROW_NUMBER()不能在GROUP BY声明中。

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

再一次澄清:我不需要SELECT TOP 1000从我的表中,因为这只是意味着我选择前1000个值(取决于排序)。我需要每个x值有SELECT,而我可以计算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”,最后将WHERE子句添加到外部SELECT中,其中我将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,请参阅下面的评论原始发帖!

+1

您能提供一些简化的数据示例和期望的输出吗? – Lamak 2012-03-19 20:23:48

+1

你能提供你正在使用的SQL版本吗?它似乎是mySQL,但在2005年,2008年等? – Sparky 2012-03-19 20:26:42

+0

@Sparky - 事实上,他确实在MS SQL上说了这个问题,所以SQL Server和使用'ROW_NUMBER'应该是2005+ – Lamak 2012-03-19 20:30:44

回答

5

从本质上讲,所有你需要做选择的第x值是保留的所有行ROWNUMBER除以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个值,你可能会使用类似这样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      
+0

这是使用窗口函数的标准做法。内部查询以获取结果并通过外部查询进行过滤。 – Bill 2012-03-19 21:36:39

+0

嗨,感谢您的快速响应,我明天就给它一个镜头,让你立即知道 - 看起来很有希望! :) – 2012-03-19 23:15:17

+1

像魅力一样工作 - 使用WHERE子句中的模数就是解决方案。非常感谢! – 2012-03-20 10:12:57

0

还有一个值得考虑的选择:

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

,但像以前的答案比这多了一个被honest-。 这个问题可能与性能有关。

+0

@Janis - 这个问题是第1000个随机记录被选中。我不认为这是OP的意图。结果集需要进行排序,并从该排序集中选择第n个值。 – 2012-03-20 20:04:27