Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Konvertieren des julianischen JDE-Datums in das gregorianische Datum

Ich denke, es ist effizienter, native Datetime-Mathematik zu verwenden, als all dieses Hin- und Herwechseln zu verschiedenen Zeichenketten-, Datums- und numerischen Formaten.

DECLARE @julian VARCHAR(6) = '111186';

SELECT DATEADD(YEAR, 
  100*CONVERT(INT, LEFT(@julian,1))
  +10*CONVERT(INT, SUBSTRING(@julian, 2,1))
  +CONVERT(INT, SUBSTRING(@julian,3,1)), 
 DATEADD(DAY, CONVERT(INT,SUBSTRING(@julian, 4, 3))-1, 
 0));

Ergebnis:

===================
2011-07-05 00:00:00

Unter der Annahme, dass sich diese Daten nicht oft ändern, kann es viel effizienter sein, das Datum tatsächlich als berechnete Spalte zu speichern (weshalb ich das Basisdatum 0 gewählt habe anstelle einer Zeichenfolgendarstellung, die zu Determinismusproblemen führen würde, die verhindern, dass die Spalte beibehalten und möglicherweise indiziert wird).

CREATE TABLE dbo.JDEDates
(
    JDEDate VARCHAR(6),

    GregorianDate AS CONVERT(SMALLDATETIME, 
      DATEADD(YEAR, 
        100*CONVERT(INT, LEFT(RIGHT('0'+JDEDate,6),1))
        +10*CONVERT(INT, SUBSTRING(RIGHT('0'+JDEDate,6), 2,1))
        +CONVERT(INT, SUBSTRING(RIGHT('0'+JDEDate,6),3,1)), 
      DATEADD(DAY, CONVERT(INT, RIGHT(JDEDate, 3))-1, 
      0))
    ) PERSISTED
);

INSERT dbo.JDEDates(JDEDate) SELECT '111186';

SELECT JDEDate, GregorianDate FROM dbo.JDEDates;

Ergebnisse:

JDEDate GregorianDate
======= ===================
111186  2011-07-05 00:00:00

Selbst wenn Sie die Spalte nicht indizieren, verbirgt es immer noch die hässliche Berechnung vor Ihnen, da Sie diese nur zum Zeitpunkt des Schreibens bezahlen, da Sie dadurch keine teuren funktionalen Vorgänge zum Zeitpunkt der Abfrage ausführen müssen, wenn auf diese Spalte verwiesen wird ...