Wir haben eine Termintabelle wie unten gezeigt. Jeder Termin muss als "Neu" oder "Follow-up" eingestuft werden. Jeder Termin (für einen Patienten) innerhalb von 30 Tagen nach dem ersten Termin (für diesen Patienten) ist Follow-up. Nach 30 Tagen ist der Termin wieder "Neu". Jeder Termin innerhalb von 30 Tagen wird zu "Follow-up".
Ich mache dies derzeit durch Eingabe von while-Schleife.
Wie kann dies ohne WHILE-Schleife erreicht werden?
Tabelle
CREATE TABLE #Appt1 (ApptID INT, PatientID INT, ApptDate DATE)
INSERT INTO #Appt1
SELECT 1,101,'2020-01-05' UNION
SELECT 2,505,'2020-01-06' UNION
SELECT 3,505,'2020-01-10' UNION
SELECT 4,505,'2020-01-20' UNION
SELECT 5,101,'2020-01-25' UNION
SELECT 6,101,'2020-02-12' UNION
SELECT 7,101,'2020-02-20' UNION
SELECT 8,101,'2020-03-30' UNION
SELECT 9,303,'2020-01-28' UNION
SELECT 10,303,'2020-02-02'
fast_forward
Cursor in Bezug auf die Leistung wahrscheinlich die beste Option wäre.Antworten:
Sie müssen eine rekursive Abfrage verwenden.
Der 30-Tage-Zeitraum wird ab prev gezählt (und nein, es ist nicht möglich, dies ohne Rekursion / skurriles Update / Schleife zu tun). Aus diesem Grund ist die gesamte vorhandene Antwort nur
ROW_NUMBER
fehlgeschlagen.db <> Geigen-Demo
Ausgabe:
Wie es funktioniert:
Ähnliche Klasse:
Bedingte SUMME unter Oracle - Verschließen einer Fensterfunktion
Sitzungsfenster (Azure Stream Analytics)
Ausführen von Total, bis eine bestimmte Bedingung erfüllt ist - Skurriles Update
Nachtrag
Verwenden Sie diesen Code niemals in der Produktion!
Es könnte in "einzelner" Runde gemacht werden (skurriles Update):
Abfrage:
db <> fiddle Quirky Update
quelle
RANGE x PRECEDING
Klausel korrekt implementiert .Sie könnten dies mit einem rekursiven cte tun. Sie sollten zuerst bei jedem Patienten nach apptDate bestellen. Dies kann durch ein gewöhnliches Verfahren erreicht werden.
Wählen Sie dann im Ankerteil Ihres rekursiven cte die erste Bestellung für jeden Patienten aus, markieren Sie den Status als "neu" und markieren Sie das apptDate als Datum des letzten "neuen" Datensatzes.
Berechnen Sie im rekursiven Teil Ihres rekursiven Cte, inkrementieren Sie zum nächsten Termin, die Differenz in Tagen zwischen dem aktuellen Termin und dem letzten "neuen" Termin. Wenn es länger als 30 Tage ist, markieren Sie es als "neu" und setzen Sie das letzte neue Termindatum zurück. Andernfalls markieren Sie es als "Follow-up" und geben Sie einfach die vorhandenen Tage seit dem neuen Termin weiter.
Schließlich wählen Sie in der Basisabfrage einfach die gewünschten Spalten aus.
Ich sollte erwähnen, dass ich diese Antwort ursprünglich gelöscht habe, da die Antwort von Abhijeet Khandagale Ihren Anforderungen mit einer einfacheren Abfrage zu entsprechen schien (nachdem ich sie ein wenig überarbeitet hatte). Aber mit Ihrem Kommentar zu Ihrer Geschäftsanforderung und Ihren hinzugefügten Beispieldaten habe ich meine nicht gelöscht, weil ich glaube, dass diese Ihren Anforderungen entspricht.
quelle
Ich bin mir nicht sicher, ob es genau das ist, was Sie implementiert haben. Eine andere Option, die neben der Verwendung von cte erwähnenswert ist, ist die Verwendung der temporären Tabelle und die Aktualisierung in "Runden". Wir werden also die temporäre Tabelle aktualisieren, während nicht alle Status korrekt eingestellt sind, und das Ergebnis iterativ erstellen. Wir können die Anzahl der Iterationen einfach mit einer lokalen Variablen steuern.
Also teilen wir jede Iteration in zwei Stufen auf.
Damit
Aktualisieren. Lesen Sie den Kommentar von Lukasz. Es ist bei weitem klüger. Ich hinterlasse meine Antwort nur als Idee.
quelle
Ich glaube, der rekursive allgemeine Ausdruck ist eine großartige Möglichkeit, Abfragen zu optimieren und Schleifen zu vermeiden. In einigen Fällen kann er jedoch zu einer schlechten Leistung führen und sollte nach Möglichkeit vermieden werden.
Ich verwende den folgenden Code, um das Problem zu lösen und zu testen, um mehr Werte zu erhalten. Ich empfehle Ihnen jedoch, es auch mit Ihren realen Daten zu testen.
Die Idee ist ziemlich einfach - ich möchte die Datensätze in Gruppen (30 Tage) trennen, in welcher Gruppe der kleinste Datensatz ist
new
, die anderenfollow ups
. Überprüfen Sie, wie die Anweisung erstellt wird:Damit:
* 1.0 / 30
wird hinzugefügt+ 0.000001
; Außerdem verwenden wir die Deckenfunktion, um die zu erhaltensmallest integer greater than, or equal to, the specified numeric expression
Das ist es. Mit einer solchen Gruppe finden wir einfach
ROW_NUMBER
unser Startdatum und machen es alsnew
und lassen den Rest alsfollow ups
.quelle
Mit gebührendem Respekt an alle und an IMHO,
Es gibt nicht viel Leistungsgewinn bei der Verwendung
Recursive CTE
undWindow Partition function
alles in einem.Appid
sollte seinint identity(1,1)
, oder es sollte immer größer werdenclustered index
.Neben anderen Vorteilen wird auch sichergestellt, dass alle aufeinanderfolgenden Reihen
APPDate
dieses Patienten größer sein müssen.Auf diese Weise können Sie problemlos mit
APPID
Ihrer Abfrage spielen, was effizienter ist, alsinequality
Operatoren wie>, <in APPDate einzufügen. Das Einfügen voninequality
Operatoren wie>, <in APPID hilft dem SQL-Optimierer.Außerdem sollte es in der Tabelle zwei Datumsspalten geben
Da dies die wichtigsten Spalten in der wichtigsten Tabelle sind, konvertieren Sie nicht viel.
So
Non clustered index
kann auf Appdate erstellt werdenTesten Sie mein Skript mit anderen Beispieldaten und ich weiß, für welche Beispieldaten es nicht funktioniert. Auch wenn es nicht funktioniert, bin ich sicher, dass es in meiner Skriptlogik selbst behoben werden kann.
quelle
Obwohl es in der Frage nicht klar angesprochen wird, ist es leicht herauszufinden, dass die Termine nicht einfach nach 30-Tage-Gruppen kategorisiert werden können. Es macht keinen geschäftlichen Sinn. Und Sie können die Appt-ID auch nicht verwenden. Man kann heute einen neuen Termin für vereinbaren
2020-09-06
. Hier ist, wie ich dieses Problem anspreche. Holen Sie sich zuerst den ersten Termin und berechnen Sie dann die Datumsdifferenz zwischen jedem Termin und der ersten App. Wenn es 0 ist, setzen Sie auf 'Neu'. Wenn <= 30 'Follow-up'. Wenn> 30, setzen Sie als "Unentschlossen" und überprüfen Sie die nächste Runde, bis "Unentschlossen" nicht mehr vorhanden ist. Und dafür brauchen Sie wirklich eine while-Schleife, aber sie durchläuft nicht jedes Termindatum, sondern nur einige wenige Datensätze. Ich habe den Ausführungsplan überprüft. Obwohl es nur 10 Zeilen gibt, sind die Abfragekosten erheblich niedriger als bei Verwendung von rekursivem CTE, jedoch nicht so niedrig wie bei der Nachtragsmethode von Lukasz Szozda.quelle
Ich hoffe, dies wird dir helfen.
quelle
Sie könnten eine
Case
Anweisung verwenden .Die Frage ist, sollte diese Kategorie basierend auf dem ersten Termin oder dem vorherigen zugewiesen werden? Das heißt, wenn ein Patient drei Termine hatte, sollten wir den dritten Termin mit dem ersten oder dem zweiten vergleichen?
Ihr Problem gibt das erste an, so habe ich geantwortet. Wenn dies nicht der Fall ist, möchten Sie verwenden
lag
.Denken Sie auch daran,
DateDiff
dass dies an Wochenenden keine Ausnahme macht. Wenn dies nur Wochentage sein sollen, müssen Sie Ihre eigene skalarwertige Funktion erstellen.quelle
mit Lag-Funktion
Demo -> https://rextester.com/TNW43808
quelle
apptDate
alsorder by
Spalte derlag
Funktion verwenden (was Sie eigentlich als ID bezeichnen sollten, ist dies keine Garantie für irgendetwas), kann sie durch die Einführung weiterer Folgetermine leicht beschädigt werden. Sehen Sie sich zum Beispiel diese Rextester-Demo an. Guter Versuch ...New
und kein sein sollteFollowUp
. Es sind mehr als 30 Tage seit dem ersten Termin dieses Patienten vergangen ... Sie sollten 30 Tage seit jedemNew
Termin zählen und dannNew
wieder einen verwenden ...Meins ist richtig. Die Autoren waren falsch, siehe abgelaufen
quelle