2013-03-07 79 views
2

我使用的是SQL Server 2012中,我試圖做這樣的事情:選擇隨機行和停止在特定金額/總達到

SELECT SUM(MILES) from tblName WHERE 
mDate > = '03/01/2012' and 
mDate <= '03/31/2012' 
-- and... 
/* 
    now I want to add here do until the SUM of Miles 
    is equal to or greater then '3250' and get the 
    results rows randomly 
*/ 
換句話說

所以,我想選擇從表中隨機選擇具有指定從當前日期開始的行,並在行程總和等於或大於數字時停止:3250

回答

3

由於您使用的是SQL Server 2012,因此這是一種更簡單的方法,不需要循環。

DECLARE @tbl TABLE(mDate DATE, Miles INT) 

INSERT @tbl VALUES 
('20120201', 520), ('20120312', 620), 
('20120313', 720), ('20120314', 560), 
('20120315', 380), ('20120316', 990), 
('20120317', 1020), ('20120412', 520); 

;WITH x AS 
(
SELECT 
    mDate, 
    Miles, 
    s = SUM(Miles) OVER 
    (
    ORDER BY NEWID() ROWS UNBOUNDED PRECEDING 
    ) 
FROM @tbl 
WHERE mDate >= '20120301' 
AND mDate < '20120401' 
) 
SELECT 
    mDate, 
    Miles, 
    s 
FROM x 
WHERE s <= 3250 
ORDER BY s; 

SQLfiddle demo - 點擊 「運行SQL」 多次看到隨機的結果。

+0

謝謝!!!!! :) – compcobalt 2013-03-07 18:36:39

0

只是示例代碼,供您瞭解概念。

create table temp(intt int) 
insert into temp values(1) 
insert into temp values(2) 
insert into temp values(3) 
insert into temp values(4) 
insert into temp values(5) 
insert into temp values(6) 
insert into temp values(7) 
insert into temp values(8) 
insert into temp values(9) 
insert into temp values(10) 
insert into temp values(11) 
insert into temp values(12) 
insert into temp values(13) 
insert into temp values(14) 
insert into temp values(15) 
insert into temp values(16) 
insert into temp values(17) 
insert into temp values(18) 
insert into temp values(19) 
insert into temp values(20) 
insert into temp values(21) 

declare @sum int = 0; 
declare @prevInt int = 0; 
while(@sum<50) 
begin 
set @prevInt = (select top(1) intt from temp order by newid()); 
set @sum = @sum + @prevInt; 
end 
set @sum = @[email protected]; 
select @sum 
drop table temp 

其原因的做法是,除非和直到你有成千上萬的記錄,因爲在它的數據被分成頁面和用更少的記錄分頁不會返回廣泛的傳播效果,在同一個頁面被擊中多個號碼時間給出相同的結果。

而且,當一個空白頁命中讓0的結果有可能是個案。(我不知道爲什麼有時一個空白頁被擊中。)

+2

有了這個查詢,你可能會總結同一行的重複項 – PinnyM 2013-03-07 18:04:44

+0

那麼他需要一個總數少於一個特定的數字。而且它的可能性非常小。 – Saksham 2013-03-07 18:18:06

+0

另外我會非常小心地宣佈「最好」和「最簡單」,不管你認爲它有多好。 – 2013-03-07 18:39:21

0

嘗試

SELECT MILES 
    , RANK() OVER (ORDER BY NEWID()) yourRank 
FROM @tblName 
WHERE miles>3250 
    AND mDate >= '03/01/2012' 
    AND mDate <= '03/31/2012' 
ORDER BY yourRank 

,然後你可以添加一個TOP 5或任何你想終止。 你肯定會隨機地得到這些。

+0

哦,只是看到你想要總里程<= 3250。需要考慮如何處理這個。但與RANK你得到隨機順序,所以1步完成:) – YvesR 2013-03-07 18:04:10

+0

PinnyM答案是正確的,將它與隨機數發生器結合,你就完成了。 – YvesR 2013-03-07 18:10:50

2

你可以做SELECT TOP x ... ORDER BY newid()得到一個隨機行的總和。問題在於確定'x'。你甚至不能確保「X」(數與查詢匹配的行)的最大價值將有足夠的共有大,首先滿足未經測試你的要求:

DECLARE @stopAt int 
DECLARE @x int 
DECLARE @result int 

SET @stopAt = 3250 
SET @x = 1 

SELECT @result = SUM(MILES) from tblName 
WHERE 
    mDate >= '03/01/2012' and 
    mDate <= '03/31/2012' 

IF (@result < @stopAt) 
    SELECT NULL -- this can't be done 
ELSE 
    BEGIN 
    WHILE (1=1) 
    BEGIN 
     SELECT TOP (@x) @result = SUM(MILES) FROM tblName 
     WHERE 
     mDate >= '03/01/2012' and 
     mDate <= '03/31/2012' 
     ORDER BY newid() 
     IF @result >= @stopAt 
     BREAK 
     SET @x = @x + 1 
    END 
    SELECT @result 
    END 

只是注意有關這個 - 算法開始,並且1遞增直到找到合適的匹配。更高效的方法(對於更大的數據集)可能包括二進制類型搜索,該搜索會緩存最低合適的結果,並在找到最深的節點(或完全匹配)時返回。

+0

+1。只有一個需求缺失,不是嗎?他希望隨機獲得結果,因此您需要爲結果添加隨機數發生器。所以如果你像我在我的回答中那樣創建了一個隨機化的等級,填充一個臨時表然後運行你的代碼,它應該完成。 – YvesR 2013-03-07 18:10:22

+0

@YvesR,使用'ORDER BY newid()' – PinnyM 2013-03-07 18:10:59

+0

好吧,沒有看到在第一次閱讀。 – YvesR 2013-03-07 18:11:32