sql >> Databasteknik >  >> RDS >> Sqlserver

Hur kan jag trunkera en datetime i SQL Server?

Detta fortsätter att ofta samla ytterligare röster, även flera år senare, och så jag måste uppdatera det för moderna versioner av SQL Server. För SQL Server 2008 och senare är det enkelt:

cast(getDate() As Date)

Observera att de tre sista styckena nära botten fortfarande gäller, och du behöver ofta ta ett steg tillbaka och hitta ett sätt att undvika gipset i första hand.

Men det finns andra sätt att åstadkomma detta också. Här är de vanligaste.

Rätt sätt (nytt sedan SQL Server 2008):

cast(getdate() As Date)

Rätt sätt (gammalt):

dateadd(dd, datediff(dd,0, getDate()), 0)

Det här är äldre nu, men det är fortfarande värt att veta eftersom det också enkelt kan anpassa sig till andra tidpunkter, som månadens första ögonblick, minut, timme eller år.

Detta korrekta sätt använder dokumenterade funktioner som ingår i ansi-standarden och som garanterat fungerar, men det kan vara något långsammare. Det fungerar genom att hitta hur många dagar det är från dag 0 till den aktuella dagen, och lägga till det många dagar tillbaka till dag 0. Det kommer att fungera oavsett hur din datetime lagras och oavsett vilken plats du har.

Det snabba sättet:

cast(floor(cast(getdate() as float)) as datetime)

Detta fungerar eftersom datetime-kolumner lagras som 8-byte binära värden. Kasta dem så att de flyter, golv dem för att ta bort bråkdelen, och tidsdelen av värdena är borta när du kastar tillbaka dem till datetime. Det hela är bara lite skiftande utan komplicerad logik och det är mycket snabb.

Var medveten om att detta är beroende av en implementeringsdetalj som Microsoft kan ändra när som helst, även i en automatisk tjänstuppdatering. Den är inte heller särskilt bärbar. I praktiken är det mycket osannolikt att den här implementeringen kommer att ändras någon gång snart, men det är fortfarande viktigt att vara medveten om faran om du väljer att använda den. Och nu när vi har möjlighet att casta som en dejt är det sällan nödvändigt.

Fel väg:

cast(convert(char(11), getdate(), 113) as datetime)

Fel sätt fungerar genom att konvertera till en sträng, trunkera strängen och konvertera tillbaka till en datetime. Det är fel , av två anledningar:1) det kanske inte fungerar på alla platser och 2) det handlar om det långsammaste sättet att göra detta... och inte bara lite; det är som en storleksordning eller två långsammare än de andra alternativen.

Uppdatera Det här har fått en del röster på sistone, så jag vill tillägga att sedan jag postade detta har jag sett några ganska solida bevis för att SQL Server kommer att optimera bort prestandaskillnaden mellan "korrekt" sätt och "snabbt" sätt, vilket betyder att du nu bör gynna den förra.

I båda fallen vill du skriva dina frågor för att undvika att behöva göra detta i första hand . Det är mycket sällsynt att du ska göra detta arbete på databasen.

På de flesta ställen är databasen redan din flaskhals. Det är generellt sett den server som är dyrast att lägga till hårdvara för att förbättra prestanda och den som är svårast att få rätt på (du måste till exempel balansera diskar med minne). Det är också svårast att skala utåt, både tekniskt och ur affärsmässig synvinkel; det är mycket enklare tekniskt sett att lägga till en webb- eller applikationsserver än en databasserver och även om det vore falskt betalar du inte $20 000+ per serverlicens för IIS eller apache.

Poängen jag försöker få fram är att närhelst det är möjligt bör du göra detta arbete på applikationsnivå. Den enda tidpunkt då du någonsin skulle komma på att du trunkerar en datetime på SQL Server är när du behöver gruppera efter dag, och även då borde du förmodligen ha en extra kolumn inställd som en beräknad kolumn, underhållen vid insättnings-/uppdateringstid eller underhålls i applikationen logik. Få detta indexbrytande, cpu-tunga arbete från din databas.



  1. 900 byte indexstorleksgräns i teckenlängd

  2. Utfasad:mysql_connect()

  3. Skapa PostgreSQL-databas i farten med Hibernate även om DB inte finns

  4. Att förstå Postgres radstorlekar