2012-01-10 56 views
3

鑑於行行內最大的連勝?

symbol_id profit date 
1   100 2009-08-18 01:01:00 
1   100 2009-08-18 01:01:01 
1   156 2009-08-18 01:01:04 
1   -56 2009-08-18 01:01:06 
1   18  2009-08-18 01:01:07 

我將如何最有效地選擇參與最偉大的連勝(利潤)的行。

最大的連勝將是前3行,我想這些行。我想出的查詢只是一堆嵌套查詢和派生表。我正在尋找一種有效的方法來使用公共表格表達式或更高級的方法來完成此操作。

+2

什麼定義'最大streak'?以高利潤結束的序列,從負利潤之後立即開始? – MatBailie 2012-01-10 16:11:49

+0

是的,利潤是連續的,負利潤結束條件 – bladefist 2012-01-10 16:43:20

回答

2

您尚未定義0利潤應該如何處理,或者如果最長連線有平行關係,會發生什麼情況。但像...

;WITH T1 AS 
(
SELECT *, 
     ROW_NUMBER() OVER (PARTITION BY symbol_id ORDER BY date) - 
     ROW_NUMBER() OVER (PARTITION BY symbol_id, SIGN(profit) 
           ORDER BY date) AS Grp 
FROM Data  
), T2 AS 
(
SELECT *, 
     COUNT(*) OVER (PARTITION BY symbol_id,Grp) AS StreakLen 
FROM T1  
) 
SELECT TOP 1 WITH TIES * 
FROM T2 
ORDER BY StreakLen DESC 

或者 - 如果你正在尋找最賺錢的連勝

;WITH T1 AS 
(
SELECT *, 
     ROW_NUMBER() OVER (PARTITION BY symbol_id ORDER BY date) - 
     ROW_NUMBER() OVER (PARTITION BY symbol_id, CASE WHEN profit >= 0 THEN 1 END 
           ORDER BY date) AS Grp 
FROM Data  
), T2 AS 
(
SELECT *, 
     SUM(profit) OVER (PARTITION BY symbol_id,Grp) AS StreakProfit 
FROM T1  
) 
SELECT TOP 1 WITH TIES * 
FROM T2 
ORDER BY StreakProfit DESC 
+0

如果序列1,2,3,4,5,4,3,4,5,6應產生3,4,5,6 '連勝。 – MatBailie 2012-01-10 16:25:18

+0

WOW。我的表中有11,618,019行,查詢立即執行。你是一個拯救生命的人。現在,我將不得不研究這個查詢並從中學習。 – bladefist 2012-01-10 17:00:39

0

如果這是一個MSSQL服務器,那麼你要考慮你的SELECT子句 和ORDER使用TOP 3 BY PROFIT DESC。 如果mysql/postgres你可能要考慮在你的select子句中使用限制 也是一樣的順序。

希望這有助於。

+0

如果在不相關的時間點有另一條記錄,140的利潤會怎樣?該序列需要建立在日期時間訂單,而不是利潤訂單... – MatBailie 2012-01-10 16:23:46

1
declare @T table 
(
    symbol_id int, 
    profit int, 
    [date] datetime 
) 

insert into @T values 
(1,   100, '2009-08-18 01:01:00'), 
(1,   100, '2009-08-18 01:01:01'), 
(1,   156, '2009-08-18 01:01:04'), 
(1,   -56, '2009-08-18 01:01:06'), 
(1,   18 , '2009-08-18 01:01:07') 

;with C1 as 
(
    select *, 
     row_number() over(order by [date]) as rn 
    from @T 
), 
C2 as 
(
    select *, 
     rn - row_number() over(order by rn) as grp 
    from C1 
    where profit >= 0 
) 
select top 1 with ties * 
from C2 
order by sum(profit) over(partition by grp) desc 

結果:

symbol_id profit  date     rn     grp 
----------- ----------- ----------------------- -------------------- -------------------- 
1   100   2009-08-18 01:01:00.000 1     0 
1   100   2009-08-18 01:01:01.000 2     0 
1   156   2009-08-18 01:01:04.000 3     0 
+0

感謝您的迴應 – bladefist 2012-01-10 19:40:56