2009-08-18 8 views
2

Gegeben Reihen:Gruppierung Aufeinanderfolgende "Siege" in einer Reihe

symbol_id profit date 
1   100 2009-08-18 01:01:00 
1   100 2009-08-18 01:01:01 
2   80  2009-08-18 01:01:02 
2   -10 2009-08-18 01:01:03 
1   156 2009-08-18 01:01:04 
2   98  2009-08-18 01:01:05 
1   -56 2009-08-18 01:01:06 
1   18  2009-08-18 01:01:07 
3   234 2009-08-18 01:01:08 
3   167 2009-08-18 01:01:09 
3   34  2009-08-18 01:01:10 

Ich bin für mittlere und größten Läufe/Streifen von Siegen (Gewinn> = 0) und Verluste (Gewinn < 0) pro SYMBOL_ID suchen.

Betrachtet man nur SYMBOL_ID = 1:

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 

können Sie sehen, gibt es drei aufeinander folgende "gewinnt", dann ein "Verlust", dann eine "win"

durchschnittlich 2 Siege ((3 + 1)/2)
größte streak 3
durchschnittlich 1 Verlust (1/1)
größte streak 1

gewünschte Abfrage Ergebnis:

symbol_id avg_winning_streak largest_winning avg_losing_streak largest_losing_streak 
1   2     3    1     1 
2   1     1    1     1 
3   3     3    0     0 

Antwort

1
SELECT symbol_id, 
     COALESCE(AVG(IF(res, cnt, NULL)), 0) AS avgwin, 
     COALESCE(MAX(IF(res, cnt, NULL)), 0) AS maxwin, 
     COALESCE(AVG(IF(NOT res, cnt, NULL)), 0) AS avglose, 
     COALESCE(MAX(IF(NOT res, cnt, NULL)), 0) AS maxlose 
FROM (
     SELECT symbol_id, streak, COUNT(*) AS cnt, res 
     FROM (
       SELECT g.*, 
         @streak := @streak + ((profit > 0) XOR @result) AS streak, 
         @result := (profit > 0) AS res 
       FROM (
         SELECT @streak := 0, 
           @result := false 
         ) vars, 
         t_game g 
       ORDER BY 
         symbol_id, date 
       ) q 
     GROUP BY 
       symbol_id, streak 
     ) q2 
GROUP BY 
     symbol_id 
+0

Ich fand tatsächlich eine andere Antwort von Ihnen, etwas sehr ähnliches zu tun. habe es etwas modifiziert und habe es meistens funktioniert ... aber das funktioniert wie es ist. Vielen Dank! –

2

Ich schrieb eine Lösung für SQL Server 2005 oder höher. Es ist Standard-SQL, aber ich weiß nicht, ob MySQL row_number() unterstützt. Sie können die CTEs bei Bedarf durch Unterabfragen ersetzen.

Beachten Sie, dass ich einen Gewinn von Null sowohl als Gewinn als auch als Verlust zähle, was nur eine Möglichkeit ist, mit Nullen umzugehen. Sie können die Ungleichheiten in diesen beiden Reihen ändern unterschiedlich Nullen zu zählen:

case when sp>=0 then 1.0*count(*) end as win_run_len_decimal, 
case when sp<=0 then 1.0*count(*) end as loss_run_len_decimal 

Hier ist die vollständige Abfrage:

with Trk as (
    select 
    symbol_id, 
    sign(profit) as sp, 
    row_number() over (
     partition by symbol_id 
     order by d 
    ) as rk, 
    row_number() over (
     partition by symbol_id,sign(profit) 
     order by d 
    ) as rksp 
    from T 
), Trk_agg as (
    select 
    symbol_id, 
    sp, 
    case when sp>=0 then 1.0*count(*) end as win_run_len_decimal, 
    case when sp<=0 then 1.0*count(*) end as loss_run_len_decimal 
    from Trk 
    group by symbol_id, sp, rk-rksp 
) 
    select 
    symbol_id, 
    avg(win_run_len_decimal) as avg_winning_streak, 
    max(win_run_len_decimal) as longest_winning_streak, 
    avg(loss_run_len_decimal) as avg_losing_streak, 
    max(loss_run_len_decimal) as longest_losing_streak 
    from Trk_agg 
    group by symbol_id; 
+0

Brilliant Lösung Rangfunktion und CTE in Verwendung, insbesondere die Aggregation. –

+0

Wie können Sie dies ändern, um die Datenzeilen zurückzugeben, die am besten sind? Soll ich dafür eine neue Frage stellen? – bladefist

Verwandte Themen