内线最大的连胜?

时间:2012-01-10 16:07:09

标签: sql sql-server-2008 gaps-and-islands

鉴于行

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行,我想要那些行。我想出的查询只是一堆嵌套查询和派生表。我正在寻找一种有效的方法来使用常见的表表达式或更高级的东西。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分:0)

如果那是MSSQL服务器,那么你想考虑在select子句中使用TOP 3 和利润下令。 如果是mysql / postgres,您可能需要考虑在select子句中使用limit 同样的顺序。

希望这会有所帮助。