Ряды внутри самой большой полосы? - PullRequest
3 голосов
/ 10 января 2012

по строкам

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 ]

2 голосов
/ 10 января 2012

Вы не определили, как следует обрабатывать 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 голос
/ 10 января 2012
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 голосов
/ 10 января 2012

Если это сервер MSSQL, то вы должны рассмотреть возможность использования TOP 3 в предложении select и ORDER BY PROFIT DESC.Если mysql / postgres, вы можете рассмотреть возможность использования limit в предложении select с тем же порядком.

надеюсь, это поможет.

...