2012-03-19 114 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

相關問題