Gibt es eine präzisere Möglichkeit, eine UTC-Uhrzeit nur in ein lokales Datum umzuwandeln?

7

Ich versuche, eine Abfrage zu schreiben, die Datensätze basierend auf dem lokalen Datumsteil nur eines UTC-Datums- / Uhrzeitfelds gruppiert.

Wenn meine Tabelle beispielsweise enthält 10/19/2012 2:00:00, sollte sie als gruppiert werden 10/18/2012, da meine Ortszeit EST (-5h) ist und ich nur am Datumsteil des Felds interessiert bin.

Ich weiß, dass ich DateAdd(day, DateDiff(day, 0, MyDate), 0)den Datumsteil nur aus dem Datum / Uhrzeit-Feld abrufen und DateAdd(minute, DateDiff(minute, GetUtcDate(), GetDate()), MyUtcDate)eine UTC-Datum / Uhrzeit in eine lokale Datums- / Uhrzeitangabe konvertieren kann .

Aber die Kombination der beiden beleidigt mich ernsthaft.

Gibt es eine bessere Möglichkeit, in SQL Server 2005 nur den Datumsteil eines UTC DateTime-Felds abzurufen, das in die Ortszeit konvertiert wurde?

  SELECT DateAdd(day, DateDiff(day, 0, DateAdd(minute, DateDiff(minute, GetUtcDate(), GetDate()), MyUtcDate)), 0)
       , Count(*)
    FROM MyTable
GROUP BY DateAdd(day, DateDiff(day, 0, DateAdd(minute, DateDiff(minute, GetUtcDate(), GetDate()), MyUtcDate)), 0)
Rachel
quelle
Ich habe keine Antwort, aber MINUTE sollte granular genug sein.
Aaron Bertrand
Ich habe kein 2005 zum Spielen, aber unterstützt es die Verwendung CROSS APPLYeines Alias ​​für eine solche Funktion?
JNK
@ AaronBertrand Ja, wird minutewahrscheinlich besser abschneiden als second. Aktualisierte meine Frage :)
Rachel
@JNK Ich denke schon, aber ich habe keine Ahnung, was ich tun würde CROSS APPLY:)
Rachel
SELECT FieldName FROM <table> CROSS APPLY (SELECT <calculation) AliasName(FieldName) GROUP BY FieldName
JNK

Antworten:

6

Wenn Sie nicht abgeneigt sind, dass eine Funktion die Drecksarbeit erledigt, hilft dies, die Aussage sauberer zu machen:

CREATE FUNCTION LocalDateFromUTCTime
(
    @UTCDateTime datetime
)
RETURNS datetime
BEGIN
    DECLARE @diff int;
    SET @diff = datediff(hh,GetUTCDate(), GetDate());
    RETURN DATEADD(day, DATEDIFF(day, 0, DATEADD(hh, @diff, @UTCDateTime)),0);
END

Sie könnten dann etwas tun wie:

SELECT dbo.LocalDateFromUTCTime(MyUTCDate), COUNT(*)
FROM MyTable
GROUP BY dbo.LocalDateFromUTCTime(MyUTCDate);

Dies macht die Aussage natürlich nicht SARGable.

Wenn die Sargabilität aufgrund der großen Anzahl von Datensätzen, die Sie möglicherweise haben, von größter Bedeutung ist, können Sie eine materialisierte Ansicht mit einem Index für das berechnete Feld erstellen.


BEARBEITEN:

Per @RichardThekiwi wird die SARGability dieser bestimmten Anweisung durch die Verwendung der Funktion nicht beeinflusst, da die Funktion weder Teil einer JOINnoch einer WHEREKlausel ist. Wo die Funktion wird verwendet, ist es nachlief alle Indizes verwendet worden wäre.

AUCH nicht der obige Code schneidet einen Zeitabschnitt des in die Funktion eingegebenen Datums ab (dies ist beabsichtigt). Daher alle Zeitzonen, in denen Protokolle implementiert sind, z. B. Prince Edward Island in Kanada (UTC -4: 30), Indien (UTC -4: 30) und Kathmandu (UTC +5: 45).

Max Vernon
quelle
3
GROUP BY und SELECT werden hier nach der Suche ausgeführt, daher sollte SARGability meiner Meinung nach eigentlich kein Problem darstellen. Übrigens, wussten Sie, dass es Zeitschritte von 1/2 Stunde gibt (ziemlich regelmäßig) und Kathmandu verwendet UTC/GMT +5:45?
19.
Vielen Dank für diese Klarstellung - Sie haben Recht, die Funktion würde die Sargabilität nur beeinträchtigen, wenn sie Teil einer WHERE-Klausel wäre oder von einem JOIN verwendet würde. Und nein, ich hatte nicht an Zeitzonen mit winziger Auflösung gedacht.
Max Vernon
3

Normalerweise benutze ich diesen Ausdruck

CAST(LEFT(GetDate() - GetUtcDate() + MyUtcDate, 11) AS DATETIME)

Unter SQL Server 2008 vereinfacht sich dies jedoch

CAST(GetDate() - GetUtcDate() + MyUtcDate AS DATE)

Abgesehen davon, dass Sie hier alternative Ausdrücke angeben, wenn Sie ein T-SQL-Purist sind, der mit DATE-Funktionen verheiratet ist, um Datenzeiten zu manipulieren, gibt es meines Erachtens keine präzisere Möglichkeit, die Ortszeit über die Verwendung einer Skalarfunktion hinaus zu ermitteln (wie Max gezeigt hat oder CLR-Funktion).

孔夫子
quelle