Czy te dwa zapytania są logicznie równoważne?
DECLARE @DateTime DATETIME = GETDATE()
Zapytanie 1
SELECT *
FROM MyTable
WHERE Datediff(DAY, LogInsertTime, @DateTime) > 7
Zapytanie 2
SELECT *
FROM MyTable
WHERE LogInsertTime < @DateTime - 7
Jeśli nie są logicznie równoważne, czy możesz podać logiczny ekwiwalent pierwszego zapytania, aby klauzula WHERE mogła efektywnie korzystać z indeksu (tj. Wyeliminować zawijanie funkcji)?
LogInsertTime
jest?Odpowiedzi:
Nie ma znaczenia, czy dwa wysłane zapytania są logicznie równoważne; nie powinieneś używać żadnego z nich. Spróbuję oderwać cię od kilku rzeczy:
LogDateTime
jest indeksowane (lub może być).Nie podoba mi się matematyka stenografii i odradzam. Jasne, że pisanie jest szybsze, ale spróbuj tego z
DATE
typem danych, a otrzymasz brzydki błąd. Znacznie lepiej to przeliterować, np .:źródło
Użyłbym następującego zapytania sargeable:
Powód: uważam, że wynik @ DateTime-7 nie jest udokumentowany. Nawet jeśli akurat jest to odpowiednik DATEADD (DZIEŃ, -7, @DataTime), może się złamać w późniejszym wydaniu.
źródło
- (Subtract): Subtracts two numbers (an arithmetic subtraction operator). Can also subtract a number, in days, from a date.
. Mimo to zgadzam się, że użycie jawnych funkcji daty sprawia, że wynikowe zapytanie jest bardziej czytelne i łatwiejsze niż „magia operatora arytmetycznego”.Nie są równoważne. Rekordy sprzed 7 dni, ale przed bieżącą porą dnia - zostaną zwrócone tylko w zapytaniu nr 2:
Porównując dni za pomocą
DATEADD
funkcji , nie bierze się pod uwagę części czasu . Funkcja zwróci 1 podczas porównywania niedzieli i poniedziałku, bez względu na porę.Próbny:
Logicznym odpowiednikiem pierwszego zapytania, które umożliwi potencjalne użycie indeksu, jest usunięcie części czasu
@DateTime
lub ustawienie czasu na0:00:00
:Powodem, dla którego pierwsze zapytanie nie może użyć indeksu,
LogInsertTime
jest to, że kolumna jest zakopana w funkcji. Zapytanie nr 2 porównuje kolumnę ze stałą wartością, która umożliwia optymalizatorowi wybór indeksuLogInsertTime
.źródło