Apa cara terbaik untuk memotong nilai datetime (untuk menghapus jam menit dan detik) di SQL Server 2008?
Sebagai contoh:
declare @SomeDate datetime = '2009-05-28 16:30:22'
select trunc_date(@SomeDate)
-----------------------
2009-05-28 00:00:00.000
Apa cara terbaik untuk memotong nilai datetime (untuk menghapus jam menit dan detik) di SQL Server 2008?
Sebagai contoh:
declare @SomeDate datetime = '2009-05-28 16:30:22'
select trunc_date(@SomeDate)
-----------------------
2009-05-28 00:00:00.000
Jawaban:
Ini terus sering mengumpulkan suara tambahan, bahkan beberapa tahun kemudian, jadi saya perlu memperbaruinya untuk versi modern Sql Server. Untuk Sql Server 2008 dan yang lebih baru, sangat sederhana:
cast(getDate() As Date)
Perhatikan bahwa tiga paragraf terakhir di dekat bagian bawah masih berlaku, dan Anda sering harus mengambil langkah mundur dan menemukan cara untuk menghindari para pemain di tempat pertama.
Tetapi ada cara lain untuk mencapai ini juga. Inilah yang paling umum.
Cara yang benar (baru sejak Sql Server 2008):
cast(getdate() As Date)
Cara yang benar (lama):
dateadd(dd, datediff(dd,0, getDate()), 0)
Ini sudah lebih tua sekarang, tetapi masih perlu diketahui karena ia juga dapat dengan mudah beradaptasi untuk titik waktu lainnya, seperti momen pertama bulan, menit, jam, atau tahun.
Cara yang benar ini menggunakan fungsi-fungsi yang didokumentasikan yang merupakan bagian dari standar ansi dan dijamin berfungsi, tetapi bisa jadi agak lambat. Ia bekerja dengan menemukan berapa hari ada dari hari 0 hingga hari ini, dan menambahkan bahwa banyak hari kembali ke hari 0. Ini akan bekerja tidak peduli berapa lama penyimpanan data Anda dan tidak peduli apa lokal Anda.
Cara cepat:
cast(floor(cast(getdate() as float)) as datetime)
Ini berfungsi karena kolom datetime disimpan sebagai nilai biner 8-byte. Buang mereka untuk mengapung, lantai mereka untuk menghapus fraksi, dan bagian waktu dari nilai-nilai hilang ketika Anda melemparkannya kembali ke datetime. Itu semua hanya sedikit bergeser tanpa logika yang rumit dan sangat cepat.
Ketahuilah bahwa ini bergantung pada detail implementasi yang dapat diubah oleh Microsoft kapan saja, bahkan dalam pembaruan layanan otomatis. Ini juga tidak terlalu portabel. Dalam praktiknya, sangat tidak mungkin implementasi ini akan berubah dalam waktu dekat, tetapi penting untuk mewaspadai bahaya jika Anda memilih untuk menggunakannya. Dan sekarang kita memiliki opsi untuk berperan sebagai kencan, jarang diperlukan.
Jalan yang salah:
cast(convert(char(11), getdate(), 113) as datetime)
Cara yang salah berfungsi dengan mengonversi string, memotong string, dan mengonversi kembali ke datetime. Itu salah , karena dua alasan: 1) mungkin tidak bekerja di semua lokal dan 2) ini tentang cara paling lambat untuk melakukan ini ... dan bukan hanya sedikit; itu seperti urutan besarnya atau dua lebih lambat dari opsi lain.
Pembaruan Ini telah mendapatkan beberapa suara akhir-akhir ini, jadi saya ingin menambahkan bahwa sejak saya memposting ini saya telah melihat beberapa bukti yang cukup kuat bahwa Sql Server akan mengoptimalkan perbedaan kinerja antara cara "benar" dan cara "cepat" , berarti Anda sekarang harus mendukung yang pertama.
Dalam kedua kasus tersebut, Anda ingin menulis kueri Anda untuk menghindari keharusan melakukan ini sejak awal . Sangat jarang Anda harus melakukan ini pada database.
Di sebagian besar tempat, basis data sudah menjadi hambatan Anda. Biasanya server yang paling mahal untuk menambahkan perangkat keras untuk peningkatan kinerja dan yang paling sulit untuk mendapatkan penambahan itu dengan benar (misalnya, Anda harus menyeimbangkan disk dengan memori). Ini juga yang paling sulit untuk diukur keluar, baik secara teknis maupun dari sudut pandang bisnis; jauh lebih mudah secara teknis untuk menambahkan server web atau aplikasi daripada server database dan bahkan jika itu salah Anda tidak membayar $ 20.000 + per lisensi server untuk IIS atau apache.
Poin yang saya coba sampaikan adalah bahwa sedapat mungkin Anda harus melakukan pekerjaan ini di tingkat aplikasi. Satu- satunya waktu Anda harus menemukan diri Anda memotong datetime pada Sql Server adalah ketika Anda perlu mengelompokkan hari, dan bahkan kemudian Anda mungkin harus memiliki kolom tambahan yang diatur sebagai kolom yang dihitung, dikelola pada waktu memasukkan / perbarui, atau dikelola dalam logika aplikasi. Dapatkan pemecahan indeks, cpu-heavy ini dari basis data Anda.
cast(getdate() as date)?
getdate()di sini ada stand-in untuk sumber datetime apa pun yang mungkin Anda miliki.
Hanya untuk SQL Server 2008
CAST(@SomeDateTime AS Date)
Kemudian masukkan kembali ke datetime jika Anda mau
CAST(CAST(@SomeDateTime AS Date) As datetime)
Demi jawaban yang lebih lengkap, inilah cara bekerja untuk memotong ke salah satu bagian tanggal turun dan termasuk menit (ganti GETDATE()dengan tanggal untuk memotong).
Ini berbeda dari jawaban yang diterima karena Anda dapat menggunakan tidak hanya dd(hari), tetapi bagian tanggal mana pun (lihat di sini ):
dateadd(minute, datediff(minute, 0, GETDATE()), 0)
Perhatikan bahwa dalam ekspresi di atas, 0ini adalah tanggal konstan pada awal tahun (1900-01-01). Jika Anda perlu memotong ke bagian yang lebih kecil, seperti detik atau milidetik, Anda perlu mengambil tanggal konstan yang lebih dekat dengan tanggal yang akan terpotong untuk menghindari luapan.
dateadd(minute, datediff(minute, 0, GETDATE()) / 15 * 15, 0)
Cuplikan yang saya temukan di web ketika saya harus melakukan ini adalah:
dateadd(dd,0, datediff(dd,0, YOURDATE))
e.g.
dateadd(dd,0, datediff(dd,0, getDate()))
DateAdd(dd, DateDiff(...), 0). Ini bisa menggigit Anda jika Anda tidak hati-hati.
Pada SQl 2005, fungsi trunc_date Anda dapat ditulis seperti ini.
(1)
CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
CAST(FLOOR( CAST( @date AS FLOAT ) )AS DATETIME)
END
Metode pertama jauh lebih bersih. Ini hanya menggunakan 3 metode panggilan termasuk CAST akhir () dan tidak melakukan penggabungan string, yang merupakan plus otomatis. Selain itu, tidak ada gips tipe besar di sini. Jika Anda dapat membayangkan bahwa cap Tanggal / Waktu dapat diwakili, maka mengubah dari tanggal ke angka dan kembali ke tanggal adalah proses yang cukup mudah.
(2)
CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
SELECT CONVERT(varchar, @date,112)
END
Jika Anda khawatir tentang implementasi datetimes (2) atau (3) oleh microsoft mungkin ok.
(3)
CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
SELECT CAST((STR( YEAR( @date ) ) + '/' +STR( MONTH( @date ) ) + '/' +STR( DAY(@date ) )
) AS DATETIME
END
Ketiga, metode yang lebih verbose. Ini membutuhkan pengelompokan tanggal ke bagian tahun, bulan, dan hari, menempatkannya bersama dalam format "yyyy / mm / dd", lalu memasukkannya kembali ke tanggal. Metode ini melibatkan 7 pemanggilan metode termasuk CAST akhir (), belum lagi string concatenation.
pilih cast (lantai (cast (getdate () as float)) sebagai datetime) Referensi ini: http://microsoftmiles.blogspot.com/2006/11/remove-time-from-datetime-in-sql-server.html
Bagi Anda yang datang ke sini mencari cara untuk memotong bidang DATETIME menjadi kurang dari satu hari penuh, misalnya setiap menit, Anda dapat menggunakan ini:
SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) + (FLOOR((CAST(GETDATE() AS FLOAT) - FLOOR(CAST(GETDATE() AS FLOAT))) * 1440.0) + (3.0/86400000.0)) / 1440.0 AS DATETIME)
jadi jika hari ini 2010-11-26 14:54:43.123maka ini akan kembali2010-11-26 14:54:00.000 .
Untuk mengubah intervalnya, gantilah 1440.0 dengan jumlah interval dalam sehari, misalnya:
24hrs = 24.0 (for every hour)
24hrs / 0.5hrs = 48.0 (for every half hour)
24hrs / (1/60) = 1440.0 (for every minute)
(Selalu letakkan .0di ujung untuk secara implisit dilemparkan ke pelampung.)
Bagi Anda bertanya-tanya apa (3.0/86400000)yang dalam perhitungan saya, SQL Server 2005 tampaknya tidak cor dari FLOATke DATETIMEakurat, jadi ini menambah 3 milidetik sebelum lantai itu.
datetime2tipe data.
Kueri ini akan memberi Anda hasil yang setara dengan trunc(sysdate)di Oracle.
SELECT *
FROM your_table
WHERE CONVERT(varchar(12), your_column_name, 101)
= CONVERT(varchar(12), GETDATE(), 101)
Semoga ini membantu!
Anda juga dapat mengekstrak tanggal using Substringdari variabel datetime dan mengembalikan ke datetime akan mengabaikan bagian waktu.
declare @SomeDate datetime = '2009-05-28 16:30:22'
SELECT cast(substring(convert(varchar(12),@SomeDate,111),0,12) as Datetime)
Selain itu, Anda dapat mengakses bagian variabel datetime dan menggabungkannya ke tanggal terpotong konstruk, seperti ini:
SELECT cast(DATENAME(year, @Somedate) + '-' +
Convert(varchar(2),DATEPART(month, @Somedate)) + '-' +
DATENAME(day, @Somedate)
as datetime)
Anda bisa melakukan ini (SQL 2008):
mendeklarasikan @SomeDate date = getdate ()
select @SomeDate
2009-05-28
TRUNC (aDate, 'DD') akan memotong min, detik dan jam
SRC: http://www.techonthenet.com/oracle/functions/trunc_date.php