Pertanyaan MS SQL Tanggal Hanya Tanpa Waktu


Pertanyaan

Halo semua,

Saya telah mengalami beberapa kebingungan selama beberapa waktu dengan dasarnya melapisi jenis DateTime SQL menggunakan T-SQL. Intinya, saya ingin mengambil nilai DateTime katakanlah 2008-12-1 14:30:12 dan jadikan itu 2008-12-1 00:00:00. Banyak pertanyaan yang kami jalankan untuk laporan menggunakan nilai tanggal dalam klausa WHERE, tetapi saya juga memiliki nilai tanggal mulai dan akhir dari suatu hari dan menggunakan ANTARA, atau saya menemukan beberapa metode lain.

Saat ini saya menggunakan yang berikut: WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam

Namun, ini tampaknya agak kikuk. Saya berharap akan ada sesuatu yang lebih sederhana seperti CAST([tstamp] AS DATE)

Beberapa tempat online merekomendasikan menggunakan DATEPART () fungsi, tetapi kemudian saya berakhir dengan sesuatu seperti ini:


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

Mungkin saya terlalu khawatir dengan sesuatu yang kecil dan jika ya tolong beri tahu saya. Saya hanya ingin memastikan hal-hal yang saya tulis seefisien mungkin. Saya ingin menghilangkan tautan yang lemah.

Ada saran?

Terima kasih,
C

Larutan

Terima kasih semua untuk umpan balik yang bagus. Banyak informasi yang berguna. Saya akan mengubah fungsi-fungsi kami untuk menghilangkan fungsi di sisi kiri operator. Meskipun sebagian besar kolom tanggal kami tidak menggunakan indeks, itu mungkin masih merupakan praktik yang lebih baik.


36
2018-01-21 21:30


asal


Jawaban:


itu sangat buruk untuk kinerja, lihatlah Hanya Dalam Basis Data, Anda Dapat Mendapat 1000% + Peningkatan Dengan Mengubah Beberapa Baris Kode

fungsi di sisi kiri operator buruk

di sini adalah apa yang perlu Anda lakukan

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)

Jalankan ini untuk melihat apa yang dilakukannya

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

34
2018-01-21 21:37



Jika Anda menggunakan SQL Server 2008, ini telah dibangun sekarang, lihat ini di buku online 

CAST(GETDATE() AS date)


70
2018-01-21 21:38



Fungsi Tanggal diposting oleh orang lain adalah cara paling tepat untuk menangani ini.

Namun, itu lucu Anda menyebut istilah "lantai", karena ada sedikit peretasan yang akan berjalan agak lebih cepat:

CAST(FLOOR(CAST(@dateParam AS float)) AS DateTime)

9
2018-01-21 21:47



CONVERT(date, GETDATE()) dan CONVERT(time, GETDATE()) bekerja di SQL Server 2008. Saya tidak yakin tentang tahun 2005.


7
2017-11-09 18:35



Bagaimana dengan ini?

SELECT DATEADD(dd, DATEDIFF(dd,0,GETDATE()), 0)

5
2018-06-06 18:45



Ya, T-SQL kadang-kadang terasa sangat primitif, dan hal-hal seperti inilah yang sering kali mendorong saya untuk melakukan banyak logika dalam bahasa pilihan saya (seperti C #).

Namun, ketika Anda benar-benar perlu melakukan beberapa hal ini di SQL untuk alasan kinerja, maka taruhan terbaik Anda adalah membuat fungsi untuk menampung "algoritme" ini.

Lihatlah artikel ini. Dia menawarkan beberapa fungsi SQL berguna di sepanjang garis-garis yang menurut saya akan membantu Anda.

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


1
2018-01-21 21:35



Hati-hati di sini, jika Anda menggunakan sesuatu yang panjang garis WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam itu akan memaksa pemindaian di atas meja dan tidak ada indeks yang akan digunakan untuk bagian itu.

Cara yang lebih bersih untuk melakukan hal ini adalah menentukan kolom terhitung

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

Dengan cara ini Anda dapat langsung memeriksa kolom d2 dan indeks akan digunakan dan Anda tidak perlu berurusan dengan konversi.


1
2018-01-21 21:53



DATEADD(d, 0, DATEDIFF(d, 0, [tstamp]))

Edit: Meskipun ini akan menghapus bagian waktu dari datetime Anda, itu juga akan membuat kondisi non SARGable. Jika itu penting untuk kueri ini, tampilan yang diindeks atau klausa di antara lebih tepat.


1
2018-01-21 21:35