2017-12-19 3 views
0

Ich habe ein SQL-Problem (auf Redshift), wo ich den Wert aus Spalte index für jeden erhalten müssen ID in Spalte id basierend auf max Wert in Spalte final_score und setzen Sie diesen Wert in eine neue Spalte fav_index. score2 ist gleich dem Wert von score1 wo index n = index n + 1, beispielsweise für id = abc1, index = 0 und score1 = 10 der Wert score2 wird der Wert von score1 sein, wo index = 1 und der Wert von final_score ist die Differenz zwischen score1 und score2.Redshift - Erhalten Sie einen Wert aus einer Spalte A für jede ID in der Gruppierungs-ID Spalte B basierend auf max Wert in einer anderen Spalte C

Es ist einfacher, wenn Sie unter Tabelle score schauen. Diese Tabelle score ist das Ergebnis einer SQL-Abfrage, die später gezeigt wird.

id index score1 score2 final_score 
abc1 0  10  20  10 
abc1 1  20  45  25 
abc1 2  45  (null) (null) 
abc2 0  5   10  5 
abc2 1  10  (null) (null) 
abc3 0  50  30  -20 
abc3 1  30  (null) (null) 

also die resultierende Tabellenspalte enthält fav_index sollte wie folgt aussehen:

id index score1 score2 final_score fav_index 
abc1 0  10  20  10    0 
abc1 1  20  45  25    1 
abc1 2  45  (null) (null)   0 
abc2 0  5   10  5    0 
abc2 1  10  (null) (null)   0 
abc3 0  50  30  -20   0 
abc3 1  30  (null) (null)   0 

Im Folgenden finden Sie das Skript Tabelle zu generieren score aus Tabelle story:

select 
    m.id, 
    m.index, 
    max(m.max) as score1, 
    fmt.score2, 
    round(fmt.score2 - max(m.max), 1) as final_score 
from 
    (select 
     sv.id, 
     case when sv.story_number % 2 = 0 then cast(sv.story_number/2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index, 
     max(sv.score1) 
    from 
     story as sv 
    group by 
     sv.id, 
     index, 
     sv.score1 
    order by 
     sv.id, 
     index 
    ) as m 
left join 
    (select 
     sv.id, 
     case when sv.story_number % 2 = 0 then cast(sv.story_number/2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index, 
     max(score1) as score2 
    from 
     story as sv 
    group by 
     id, 
     index 
    ) as fmt 
    on 
     m.id = fmt.id 
    and 
     m.index = fmt.index - 1 
group by 
    m.id, 
    m.index, 
    fmt.score2 

Tabelle story ist als unten:

id story_number score1 
abc1 1    10 
abc1 2    10 
abc1 3    20 
abc1 4    20 
abc1 5    45 
abc1 6    45 

Die einzige Lösung, die ich denken kann, ist so etwas wie zu tun,

select id, max(final_score) from score group by id 

und es dann auf die lange Skript kommt wieder über (die verwendet wurde, Tabelle zu generieren score). Ich möchte wirklich vermeiden, ein so langes Skript zu schreiben, um nur eine zusätzliche Spalte mit Informationen zu bekommen, die ich brauche.

Gibt es einen besseren Weg, dies zu tun?

Vielen Dank!

Update: Antwort in mysql wird auch akzeptiert. Vielen Dank!

+0

'MySQL' oder' SQL Server'? – Squirrel

+1

Bitte entfernen Sie mysql als Tag/aktualisieren Sie Ihren Kommentar, da mysql nichts mit Rotverschiebung zu tun hat. –

+2

Sie sind falsch - MySQL ist kein universeller Begriff und es ist ganz anders als Rotverschiebung. Eine mysql-Antwort auf diese Frage würde fast sicher nicht funktionieren, selbst wenn die Rotverschiebung geändert würde. –

Antwort

0

Nach mehr Stunden auf diesen Ausgaben und die Leute zu fragen um, ich schließlich eine Lösung, die durch Bezugnahme auf diese Fensterfunktion Dokumentation herausgefunden - PostgreSQL https://www.postgresql.org/docs/9.1/static/tutorial-window.html

Ich habe im Grunde 2 x select Anweisungen oben und 1 x where Aussage ganz unten. Die where Anweisung ist, auf die Zeilen zu achten, in denen final_score = null ist, weil andernfalls die rank() Funktion sie als 1 einstufen wird.

Mein Code wird dann:

select 
    id, index, final_score, rank, case when rank = 1 then index else null end as fav_index 
from 
(select 
    id, index, final_score, rank() over (partition by id order by final_score desc) 
from 
(select 
    m.id, 
    m.index, 
    max(m.max) as score1, 
    fmt.score2, 
    round(fmt.score2 - max(m.max), 1) as final_score 
from 
    (select 
     sv.id, 
     case when sv.story_number % 2 = 0 then cast(sv.story_number/2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index, 
     max(sv.score1) 
    from 
     story as sv 
    group by 
     sv.id, 
     index, 
     sv.score1 
    order by 
     sv.id, 
     index 
    ) as m 
left join 
    (select 
     sv.id, 
     case when sv.story_number % 2 = 0 then cast(sv.story_number/2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index, 
     max(score1) as score2 
    from 
     story as sv 
    group by 
     id, 
     index 
    ) as fmt 
    on 
     m.id = fmt.id 
    and 
     m.index = fmt.index - 1 
group by 
    m.id, 
    m.index, 
    fmt.score2) 
where 
    final_score is not null) 

Und das Ergebnis ist wie folgt:

id index final_score rank  fav_index 
abc1 0  10    2  (null) 
abc1 1  25    1  1 
abc2 0  5    1  0 
abc3 0  -20   1  0 

Ergebnis als etwas anders ist, was ich in der Frage angegeben, jedoch ist die fav_index für jede ID identifiziert und das ist, was ich wirklich brauchte. Hoffe, das könnte jemandem helfen. Prost

Verwandte Themen