1

Ich habe eine Spalte INT in meiner Tabelle. In dieser Spalte wird das Datum in einem speziellen Format gespeichert. Ich versuche, diese Spalte in DATE-Typ zu konvertieren.Nummer in Datum in SQL Server mit Ausnahme in Monatsende konvertieren

Zum Beispiel behalten wir '2016-03-14' als 20160314.

Die Ausnahme ist, dass wir für den letzten eines jeden Monats keinen Tag speichern. Also für '2016-03-31' speichern wir 201603 und ich muss prüfen, ob die Nummer less than 999999 oder nicht zu finden ist die Zahl ein Monatsende oder andere Tage im Monat darstellt.

Bisher habe ich zwei Abfragen, diese Aufgabe zu erreichen:

Abfrage 1:

Das ist alles Mathematik Formel.

declare @k int = 20160321 
--declare @k int = 201603 
select 
    IIF(@k < 999999 
     , EOMONTH(DATEFROMPARTS(@k /100, @k % 100, 1), 0) 
     , DATEFROMPARTS(@k /10000, (@k/100) % 100, @k % 100) 
    ) 

Abfrage 2: Dieser String-Manipulation verwendet.

declare @k int = 20160321 
--declare @k int = 201603 

select 
    IIF(@k < 999999 
     , EOMONTH(cast(LEFT(@k, 4) + '-' + RIGHT(@k, 2) + '-01' as date), 0) 
     , cast(LEFT(@k, 4) + '-' + RIGHT(LEFT(@k, 6), 2) + '-' + RIGHT(@k, 2) as date) 
    ) AS DateColumn 

Ich brauche die Umrechnungsformeln in WHERE Klausel zu tun. Etwas wie:

SELECT K, Dt, Name -- and more fields 
FROM tbl 
WHERE IIF(K < 999999 
      , EOMONTH(DATEFROMPARTS(K /100, K % 100, 1), 0) 
      , DATEFROMPARTS(K /10000, (K/100) % 100, K % 100) 
     ) < GetDate() 

Und performance is important

Frage: Gibt es einen besseren Weg, dies zu tun? Möglicherweise eine Möglichkeit, wie SQL Server den Clustered-Index verwenden kann, den ich in der K-Spalte habe.

+0

@hvd Er ist nicht. Er verwendet die Funktion EOMONTH(), die das Datum des letzten Tages des Monats zurückgibt. –

+0

@hvd - ich denke, er hat das durch den Aufruf der 'EOMONTH' Funktion abgedeckt –

+0

Ja Leute. Es könnte andere Wege geben, die denen, die ich gemacht habe, sehr ähnlich sind. Der Biestfall würde das tun, so dass SQL Server den Clustered-Index von have on K-Spalte verwenden kann. Ich füge das zum Körper der Frage hinzu. – FLICKER

Antwort

1

Ich würde erwarten, dass Abfrage 1 würde eine bessere Leistung, aber Sie müssten es testen, um sicher zu sein. Ich habe keine Ahnung welche Art von Performance datefromparts() und datetimefromparts() haben. Sie sind relativ neu, also würde es mich nicht schockieren, wenn sie ohne guten Grund magisch schrecklich wären. Sie vergleichen die Leistung von Zeichenfolgenmanipulation und Typcasting mit der Leistung von Arithmetik und Typcasting. Meine Vermutung ist, dass es meistens eine Wäsche ist, aber diese Arithmetik ist wahrscheinlich schneller.

Die Optionen, die mich für eine Lösung Leistung schlagen, sind: a) Fügen Sie eine Datetime-Spalte zu Ihrer Tabelle hinzu. b) Fügen Sie der Tabelle eine berechnete Spalte hinzu. Wenn Sie eine PERSISTED-Spalte erstellen, können Sie sogar einen Index dafür erstellen. c) Erstellen Sie eine Ansicht (eine indizierte Sicht, wenn Sie durch die Anforderungsringe springen können). d) Erstellen Sie eine neue Tabelle mit dem Feld datetime und aktualisieren Sie sie.

Beide (a) und (d) duplizieren Daten, daher sind sie nicht so groß wie die Lösungen, die sie zuerst erscheinen.

Ich habe immer gefunden, dass berechnete Spalten ein wenig eklig sind, aber sie funktionieren gut genug. Wenn Sie eine Ansicht erstellen, müssen Sie INNER JOIN zurückholen, um sie zu verwenden, aber in den meisten Systemen sind JOINS sehr schnell.

Ich würde wahrscheinlich eine persistente berechnete Spalte oder eine Ansicht erstellen. Die beste Lösung ist natürlich, Daten nicht als ganze Zahlen zu speichern.


Sie können diese Abfrage versuchen:

SELECT CASE 
     WHEN @K < 999999 THEN EOMONTH(TRY_CONVERT(date, CAST(@K * 100 + 1 AS VARCHAR(10)))) 
     ELSE TRY_CONVERT(date, CAST(@K AS VARCHAR(10))) 
    END AS K_Date 

Der Grund dafür funktionieren könnte, ist, dass YYYYMMDD eines der Datumsformate ISO ist. Ich würde TRY_CONVERT() vor CONVERT() versuchen, weil die Abfrage-Engine entscheiden kann, alle CONVERT ohne Blick auf die CASE bedingten und werfen Fehler auszuwerten.

+0

Danke @Bacon. Du kennst also keine andere Formel/Abfrage anders als was ich implementiert habe? – FLICKER

+0

@FLICKER Oh, richtig. Siehe mein Update. –

+0

Ich werde das versuchen und sehen, wie es funktioniert. Ich habe auch den Syntaxfehler in Ihrer Anfrage behoben – FLICKER