it-swarm.com.de

MS SQL-Datum nur ohne Uhrzeit

Frage

Hallo alle,

Ich habe seit geraumer Zeit einige Verwirrung darüber gehabt, einen DateTime-SQL-Typ mit T-SQL im Wesentlichen zu belegen. Im Wesentlichen möchte ich einen DateTime-Wert von "say 2008-12-1 14:30:12" als "2008-12-1 00:00:00" definieren. Viele der Abfragen, die wir für Berichte ausführen, verwenden einen Datumswert in der WHERE-Klausel, aber ich habe entweder einen Start- und Enddatumswert eines Tages und verwende ein ZWISCHEN oder ich finde eine andere Methode.

Derzeit verwende ich Folgendes: WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam

Dies scheint jedoch ein bisschen klobig. Ich hatte gehofft, es gäbe etwas Einfacheres wie CAST([tstamp] AS DATE)

Einige Orte im Internet empfehlen die Verwendung der DATEPART () - Funktion, aber dann erhalte ich ungefähr Folgendes:


WHERE DATEPART(year, [tstamp]) = DATEPART(year, @dateParam)
AND DATEPART(month, [tstamp]) = DATEPART(month, @dateParam)
AND DATEPART(day, [tstamp]) = DATEPART(day, @dateParam)

Vielleicht bin ich übermäßig mit etwas Kleinem beschäftigt, und wenn ja, lassen Sie es mich bitte wissen. Ich möchte nur sicherstellen, dass das, was ich schreibe, so effizient wie möglich ist. Ich möchte alle schwachen Glieder beseitigen.

Irgendwelche Vorschläge?

Vielen Dank,
C

Lösung

Vielen Dank an alle für das tolle Feedback. Viele nützliche Informationen. Ich werde unsere Funktionen ändern, um die Funktion auf der linken Seite des Bedieners zu entfernen. Obwohl die meisten unserer Datumsspalten keine Indizes verwenden, ist dies wahrscheinlich immer noch eine bessere Vorgehensweise.

38
regex

das ist sehr schlecht für die Leistung, werfen Sie einen Blick auf Nur in einer Datenbank können Sie 1000% + Verbesserung erzielen, indem Sie ein paar Codezeilen ändern

funktionen auf der linken Seite des Bedieners sind schlecht

hier ist, was Sie tun müssen

declare @d datetime
select @d =  '2008-12-1 14:30:12'

where tstamp >= dateadd(dd, datediff(dd, 0, @d)+0, 0)
and tstamp < dateadd(dd, datediff(dd, 0, @d)+1, 0)

Führen Sie dies aus, um zu sehen, was es tut

select dateadd(dd, datediff(dd, 0, getdate())+1, 0)
select dateadd(dd, datediff(dd, 0, getdate())+0, 0)
35
SQLMenace

Wenn Sie SQL Server 2008 verwenden, ist dies jetzt integriert. Lesen Sie hierzu Onlinedokumentation

CAST(GETDATE() AS date)

81
JoshBerke

Die Datumsfunktionen, die von anderen veröffentlicht wurden, sind die korrekteste Methode, um damit umzugehen.

Es ist jedoch lustig, dass Sie den Begriff "Boden" erwähnen, weil es einen kleinen Hack gibt, der etwas schneller abläuft:

CAST(FLOOR(CAST(@dateParam AS float)) AS DateTime)
9
Joel Coehoorn

CONVERT(date, GETDATE()) und CONVERT(time, GETDATE()) funktionieren in SQL Server 2008. Ich bin mir über 2005 nicht sicher.

7
AaronS

Wie wäre es damit?

SELECT DATEADD(dd, DATEDIFF(dd,0,GETDATE()), 0)
5
Sameer
DATEADD(d, 0, DATEDIFF(d, 0, [tstamp]))

Bearbeiten: Dadurch wird zwar der Zeitanteil Ihrer Datums- und Uhrzeitangabe entfernt, es wird jedoch auch die Bedingung non SARGable erstellt. Wenn dies für diese Abfrage wichtig ist, ist eine indizierte Sicht oder eine between-Klausel besser geeignet.

1
Mark Brackett

Ja, T-SQL kann sich manchmal extrem primitiv anfühlen, und es sind Dinge wie diese, die mich oft dazu zwingen, einen Großteil meiner Logik in der Sprache meiner Wahl (wie C #) auszuführen.

Wenn Sie jedoch einige dieser Dinge aus Leistungsgründen unbedingt in SQL ausführen müssen, sollten Sie am besten Funktionen erstellen, um diese "Algorithmen" aufzunehmen.

Schauen Sie sich diesen Artikel an. Er bietet einige nützliche SQL-Funktionen in dieser Richtung, von denen ich denke, dass sie Ihnen helfen werden.

http://weblogs.sqlteam.com/jeffs/archive/2007/01/02/56079.aspx

1
Lusid

Vorsicht, wenn Sie die Zeilen von WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam lang verwenden, wird ein Scan für die Tabelle erzwungen, und für diesen Teil werden keine Indizes verwendet.

Eine viel sauberere Methode ist das Definieren einer berechneten Spalte

create table #t (
    d datetime, 

    d2 as 
        cast (datepart(year,d) as varchar(4)) + '-' +
        right('0' + cast (datepart(month,d) as varchar(2)),2) + '-' + 
        right('0' + cast (datepart(day,d) as varchar(2)),2) 
) 
-- notice a lot of care need to be taken to ensure the format is comparable. (zero padding)

insert #t 
values (getdate())

create index idx on #t(d2)

select d2, count(d2) from #t 
where d2 between '2008-01-01' and '2009-01-22'
group by d2
-- index seek is used

Auf diese Weise können Sie die d2-Spalte direkt überprüfen, und es wird ein Index verwendet, und Sie müssen sich nicht mit Conversions herumschlagen.

1
Sam Saffron

Alternativ könnten Sie verwenden

declare @d datetimeselect
@d =  '2008-12-1 14:30:12'
where tstamp 
  BETWEEN dateadd(dd, datediff(dd, 0, @d)+0, 0) 
  AND dateadd(dd, datediff(dd, 0, @d)+1, 0)
0
Xander

Hier ist eine Abfrage, die alle Ergebnisse innerhalb eines Zeitraums von Tagen zurückgibt.

DECLARE @startDate DATETIME
DECLARE @endDate DATETIME

SET @startDate = DATEADD(day, -30, GETDATE())
SET @endDate = GETDATE()

SELECT *
FROM table
WHERE dateColumn >= DATEADD(day, DATEDIFF(day, 0, @startDate), 0)
  AND dateColumn <  DATEADD(day, 1, DATEDIFF(day, 0, @endDate))
0
Rob Boek

FWIW, ich mache seit Jahren dasselbe wie Sie

CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam 

Mir scheint, dass dies eine der besseren Möglichkeiten ist, die Zeit in Bezug auf Flexibilität, Geschwindigkeit und Lesbarkeit zu verkürzen. (Es tut uns leid). Einige der vorgeschlagenen UDF-Funktionen können nützlich sein, aber UDFs können bei größeren Ergebnismengen langsam sein.

0
Booji Boy