Hier ist das Problem, das ich habe: Ich habe eine große Abfrage, die Datumsangaben in der WHERE-Klausel vergleichen muss, um zu sehen, ob zwei Daten am selben Tag sind. Meine derzeitige Lösung, die saugt, besteht darin, die Datumsangaben in eine UDF zu senden, um sie in Mitternacht desselben Tages zu konvertieren, und dann diese Daten auf Gleichheit zu überprüfen. Wenn es um den Abfrageplan geht, ist dies ein Desaster, wie fast alle UDFs in Joins oder Where-Klauseln. Dies ist einer der wenigen Bereiche in meiner Anwendung, in dem ich nicht in der Lage war, die Funktionen zu rooten und dem Abfrageoptimierer etwas zu geben, das er tatsächlich verwenden kann, um den besten Index zu finden.Was ist ein guter Weg, um zu überprüfen, ob zwei Datumsangaben am selben Kalendertag in TSQL sind?
In diesem Fall scheint das Zusammenführen des Funktionscodes zurück in die Abfrage unpraktisch.
Ich denke, ich vermisse etwas Einfaches hier.
Hier ist die Funktion als Referenz.
if not exists (select * from dbo.sysobjects
where id = object_id(N'dbo.f_MakeDate') and
type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
exec('create function dbo.f_MakeDate() returns int as
begin declare @retval int return @retval end')
go
alter function dbo.f_MakeDate
(
@Day datetime,
@Hour int,
@Minute int
)
returns datetime
as
/*
Creates a datetime using the year-month-day portion of @Day, and the
@Hour and @Minute provided
*/
begin
declare @retval datetime
set @retval = cast(
cast(datepart(m, @Day) as varchar(2)) +
'/' +
cast(datepart(d, @Day) as varchar(2)) +
'/' +
cast(datepart(yyyy, @Day) as varchar(4)) +
' ' +
cast(@Hour as varchar(2)) +
':' +
cast(@Minute as varchar(2)) as datetime)
return @retval
end
go
Angelegenheiten zu erschweren, Ich trete auf Tabellen Zeitzone das Datum gegen die lokale Zeit zu überprüfen, die für jede Zeile anders sein könnte:
where
dbo.f_MakeDate(dateadd(hh, tz.Offset +
case when ds.LocalTimeZone is not null
then 1 else 0 end, t.TheDateINeedToCheck), 0, 0) = @activityDateMidnight
[Bearbeiten]
I bin mit @ Todds Vorschlag:
where datediff(day, dateadd(hh, tz.Offset +
case when ds.LocalTimeZone is not null
then 1 else 0 end, t.TheDateINeedToCheck), @ActivityDate) = 0
Mein Missverständnis darüber, wie datediff funktioniert (am selben Tag des Jahres in aufeinanderfolgenden Jahren ergibt 366, nicht 0, wie ich erwartet hatte) verursachte mir eine Menge Mühe zu verschwenden.
Aber der Abfrageplan hat sich nicht geändert. Ich denke, ich muss mit dem ganzen Ding zurück zum Zeichenbrett gehen.
Bitte beachten Sie Mark Brackett Antwort, die das ** Recht ** ist. Ich weiß, dass deine Frage 2 Jahre alt ist, aber lass uns bitte nicht die falschen Leute führen, die diese Frage besuchen. Todd Tingens Antwort funktioniert, ist aber eine schreckliche Leistung, wie Sie zu der Zeit gefunden haben! – ErikE
Die Antwort von Mark ist für diese Situation korrekt, weil der Optimierer davon abhängig war. Mit dateadd kann ich auf einfache und übersichtliche Weise feststellen, ob zwei Daten am gleichen Kalendertag liegen, was die ursprüngliche Frage war. – Todd