Apakah kedua pertanyaan ini setara secara logis?

10

Apakah kedua pertanyaan ini setara secara logis?

DECLARE @DateTime DATETIME = GETDATE()

Pertanyaan 1

SELECT *
FROM   MyTable
WHERE  Datediff(DAY, LogInsertTime, @DateTime) > 7   

Pertanyaan 2

SELECT *
FROM   MyTable
WHERE  LogInsertTime < @DateTime - 7 

Jika mereka tidak setara secara logis, dapatkah Anda memberi saya persamaan logis dari permintaan pertama sehingga klausa WHERE dapat menggunakan indeks secara efektif (mis. Menghilangkan pembungkus fungsi)?

Alf47
sumber
Jenis apa LogInsertTimeitu
dezso
LogInsertTime adalah DATETIME
Alf47

Jawaban:

15

Apakah dua pertanyaan yang Anda posting setara secara logis tidak relevan; Anda seharusnya tidak menggunakan keduanya. Saya akan mencoba untuk menjauhkan Anda dari beberapa hal:

  1. Jika memungkinkan, cobalah untuk menghindari penerapan fungsi ke kolom. Itu selalu baik, dan sebagian besar lebih baik, untuk menjaga perhitungan terhadap konstanta dan bukan kolom - ini dapat menghancurkan SARGability dan membuat indeks pada kolom tersebut tidak berguna. Dalam hal ini, saya lebih suka query 2, terutama jika LogDateTimediindeks (atau mungkin pernah).
  2. Saya tidak suka matematika tanggal steno dan saya merekomendasikan untuk tidak melakukannya. Tentu, ini lebih cepat untuk mengetik, tetapi cobalah dengan DATEtipe data dan Anda akan mendapatkan kesalahan buruk. Jauh lebih baik untuk menjelaskannya, misalnya:

    WHERE LogInsertTime < DATEADD(DAY, -7, @DateTime);
Aaron Bertrand
sumber
Saya setuju, tujuan saya adalah mengubah kueri 1 menjadi sesuatu yang mirip dengan kueri 2 sehingga indeks dapat digunakan secara efektif. Terima kasih atas bantuan Anda
Alf47
8

Saya akan menggunakan permintaan isi ulang berikut:

SELECT * FROM MyTable WHERE LogInsertTime < DATEADD(DAY, -7, @DateTime)

Alasannya: Saya percaya bahwa hasil dari @ DateTime-7 tidak didokumentasikan. Bahkan jika itu kebetulan setara dengan DATEADD (DAY, -7, @DateTime), itu mungkin pecah dalam rilis nanti.

AK
sumber
Hebat itulah yang saya cari, terima kasih
Alf47
2
Hal ini, pada kenyataannya, didokumentasikan dan didefinisikan dengan baik : - (Subtract): Subtracts two numbers (an arithmetic subtraction operator). Can also subtract a number, in days, from a date.. Namun, saya setuju bahwa menggunakan fungsi tanggal eksplisit membuat kueri yang dihasilkan lebih mudah dibaca dan dipelihara daripada "sihir operator aritmatika".
Heinzi
6

Mereka tidak setara. Catatan yang 7 hari yang lalu, tetapi sebelum waktu saat ini hari - hanya akan dikembalikan dalam permintaan # 2:

Ketika membandingkan hari menggunakan DATEADDfungsi , itu tidak mengambil bagian waktu menjadi pertimbangan . Fungsi akan mengembalikan 1 ketika membandingkan hari Minggu & Senin, terlepas dari waktu.

Demo:

DECLARE @MyTable TABLE(pk INT, LogInsertTime DATETIME);

INSERT @MyTable
VALUES (1, DATEADD(HOUR, 1, CAST(DATEADD(DAY, -7, CAST (GETDATE() AS DATE))AS DATETIME))),
(2, DATEADD(HOUR, 23, CAST(DATEADD(DAY, -7, CAST (GETDATE() AS DATE)) AS DATETIME)));

DECLARE @DateTime DATETIME = GETDATE();

SELECT *
FROM @MyTable
WHERE DATEDIFF(DAY, LogInsertTime, @DateTime) > 7;

-- 0 records.

SELECT *
FROM @MyTable
WHERE LogInsertTime < @DateTime - 7;
-- 1 record.

Setara logis dari permintaan pertama yang akan memungkinkan penggunaan indeks potensial adalah dengan menghapus bagian waktu @DateTimeatau mengatur waktu untuk 0:00:00:

SELECT *
FROM @MyTable
WHERE LogInsertTime < CAST(@DateTime - 7 AS DATE);

Alasan mengapa kueri pertama tidak dapat menggunakan indeks LogInsertTimeadalah karena kolom dimakamkan dalam suatu fungsi. Kueri # 2 membandingkan kolom dengan nilai konstan yang memungkinkan pengoptimal untuk memilih indeks LogInsertTime.

The Scrum Meister
sumber