Ich habe eine SQL-Geige für diese Frage erstellt, wenn dies für jemanden einfacher ist.
Ich habe eine Art Fantasy-Sportdatenbank und ich versuche herauszufinden, wie ich mit "aktuellen Streak" -Daten aufwarten kann (wie "W2", wenn die Mannschaft die letzten zwei Spiele gewonnen hat, oder "L1", wenn sie verloren hat ihre letzte Begegnung nach dem Gewinn der vorherigen Begegnung (oder 'T1', wenn sie ihre letzte Begegnung verloren haben).
Hier ist mein Grundschema:
CREATE TABLE FantasyTeams (
team_id BIGINT NOT NULL
)
CREATE TABLE FantasyMatches(
match_id BIGINT NOT NULL,
home_fantasy_team_id BIGINT NOT NULL,
away_fantasy_team_id BIGINT NOT NULL,
fantasy_season_id BIGINT NOT NULL,
fantasy_league_id BIGINT NOT NULL,
fantasy_week_id BIGINT NOT NULL,
winning_team_id BIGINT NULL
)
Ein Wert NULL
in der winning_team_id
Spalte zeigt ein Unentschieden für diese Übereinstimmung an.
Hier ist eine Beispiel-DML-Anweisung mit einigen Beispieldaten für 6 Teams und Matchups im Wert von 3 Wochen:
INSERT INTO FantasyTeams
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6
INSERT INTO FantasyMatches
SELECT 1, 2, 1, 2, 4, 44, 2
UNION
SELECT 2, 5, 4, 2, 4, 44, 5
UNION
SELECT 3, 6, 3, 2, 4, 44, 3
UNION
SELECT 4, 2, 4, 2, 4, 45, 2
UNION
SELECT 5, 3, 1, 2, 4, 45, 3
UNION
SELECT 6, 6, 5, 2, 4, 45, 6
UNION
SELECT 7, 2, 6, 2, 4, 46, 2
UNION
SELECT 8, 3, 5, 2, 4, 46, 3
UNION
SELECT 9, 4, 1, 2, 4, 46, NULL
GO
Hier ist ein Beispiel für die gewünschte Ausgabe (basierend auf der obigen DML), bei der ich Probleme habe, selbst wenn ich anfange herauszufinden, wie ich sie ableiten soll:
| TEAM_ID | STEAK_TYPE | STREAK_COUNT |
|---------|------------|--------------|
| 1 | T | 1 |
| 2 | W | 3 |
| 3 | W | 3 |
| 4 | T | 1 |
| 5 | L | 2 |
| 6 | L | 1 |
Ich habe verschiedene Methoden mit Unterabfragen und CTE's ausprobiert, aber ich kann es nicht zusammensetzen. Ich möchte die Verwendung eines Cursors vermeiden, da ich in Zukunft ein großes Dataset haben könnte, mit dem dies ausgeführt werden kann. Ich habe das Gefühl, dass es eine Möglichkeit geben könnte, Tabellenvariablen einzubeziehen, die diese Daten irgendwie mit sich selbst verbinden, aber ich arbeite noch daran.
Zusätzliche Informationen: Es kann eine unterschiedliche Anzahl von Teams geben (jede gerade Anzahl zwischen 6 und 10), und die Gesamtzahl der Matchups erhöht sich jede Woche um 1 pro Team. Irgendwelche Ideen, wie ich das machen soll?
quelle
bigint
für so viele Spalten, woint
würde das wohl gehen 3) warum all die_
s ?! 4) Ich bevorzuge Tabellennamen als Singular,Antworten:
Da Sie mit SQL Server 2012 arbeiten, können Sie einige der neuen Fensterfunktionen verwenden.
SQL-Geige
C1
berechnet diestreak_type
für jede Mannschaft und jedes Spiel.C2
findet die vorherigestreak_type
geordnet nachmatch_id desc
.C3
Erzeugt eine laufende Summe,streak_sum
die durchmatch_id desc
Beibehalten eines0
langen Zeichens, dasstreak_type
dem letzten Wert entspricht, bestellt wird.Die Hauptabfrage fasst die Streifen zusammen, in denen sie sich
streak_sum
befinden0
.quelle
LEAD()
. Nicht genug Leute wissen über die neuenFantasyTeams JOIN FantasyMatches
mitFantasyMatches CROSS APPLY (VALUES (home_fantasy_team_id), (away_fantasy_team_id))
und damit potenziell die Leistung verbessern.FantasyTeams
, ist es wahrscheinlich besser, stattdessen an der Hauptabfrage teilzunehmen.Ein intuitiver Ansatz zur Lösung dieses Problems ist:
Diese Strategie könnte sich gegenüber der Fensterfunktionslösung (die einen vollständigen Scan der Daten durchführt) durchsetzen, wenn die Tabelle größer wird, vorausgesetzt, die rekursive Strategie wird effizient implementiert. Der Schlüssel zum Erfolg besteht darin, effiziente Indizes bereitzustellen, um Zeilen schnell zu finden (mithilfe von Suchen) und Sortierungen zu vermeiden. Die benötigten Indizes sind:
Um die Abfrageoptimierung zu unterstützen, verwende ich eine temporäre Tabelle, um Zeilen zu speichern, die als Teil eines aktuellen Strips identifiziert wurden. Wenn die Streifen normalerweise kurz sind (was leider für die Mannschaften gilt, denen ich folge), sollte diese Tabelle recht klein sein:
Meine Lösung für rekursive Abfragen lautet wie folgt ( SQL Fiddle hier ):
Der T-SQL-Text ist ziemlich lang, aber jeder Abschnitt der Abfrage entspricht genau dem allgemeinen Ablauf, der zu Beginn dieser Antwort angegeben wurde. Die Abfrage wird länger, da bestimmte Tricks verwendet werden müssen, um Sortierungen zu vermeiden und einen
TOP
rekursiven Teil der Abfrage zu erzeugen (was normalerweise nicht zulässig ist).Der Ausführungsplan ist im Vergleich zur Abfrage relativ klein und einfach. Ich habe den Ankerbereich gelb und den rekursiven Teil grün im folgenden Screenshot schattiert:
Mit den in einer temporären Tabelle erfassten Streifenzeilen ist es einfach, die gewünschten Zusammenfassungsergebnisse zu erhalten. (Durch die Verwendung einer temporären Tabelle wird auch ein Sortierungsverlust vermieden, der auftreten kann, wenn die folgende Abfrage mit der rekursiven Hauptabfrage kombiniert wird.)
Dieselbe Abfrage kann als Grundlage für die Aktualisierung der
FantasyTeams
Tabelle verwendet werden:Oder wenn Sie es vorziehen
MERGE
:Bei beiden Ansätzen wird ein effizienter Ausführungsplan erstellt (basierend auf der bekannten Anzahl von Zeilen in der temporären Tabelle):
Schließlich
match_id
ist es einfach, eine Liste dermatch_id
s, die jeden Streifen bilden, zur Ausgabe hinzuzufügen , da die rekursive Methode natürlich die in ihrer Verarbeitung enthält :Ausgabe:
Ausführungsplan:
quelle
EXISTS (... INTERSECT ...)
anstelle von nur verwendet wirdStreaks.streak_type = CASE ...
? Ich weiß, dass die erste Methode nützlich sein kann, wenn Sie NULL-Werte auf beiden Seiten sowie Werte abgleichen müssen, aber es ist nicht so, als ob der richtige Teil in diesem Fall NULL-Werte erzeugen könnte, also ...CASE
verwendet, kann das Optimierungsprogramm keine Zusammenführungsverkettung verwenden (die die Reihenfolge der Unionsschlüssel beibehält) und verwendet stattdessen eine Verkettung mit mehreren Sortierungen.Ein anderer Weg, um das Ergebnis zu erhalten, ist ein rekursiver CTE
SQLFiddle- Demo
quelle