이 두 쿼리는 논리적으로 동일합니까?


10

이 두 쿼리는 논리적으로 동일합니까?

DECLARE @DateTime DATETIME = GETDATE()

쿼리 1

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

쿼리 2

SELECT *
FROM   MyTable
WHERE  LogInsertTime < @DateTime - 7 

그것들이 논리적으로 동일하지 않은 경우 WHERE 절이 효과적으로 인덱스를 사용할 수 있도록 첫 번째 쿼리와 논리적으로 동등한 것을 줄 수 있습니까?


어떤 타입 LogInsertTime입니까?
dezso


LogInsertTime은 DATETIME입니다
Alf47

답변:


15

게시 한 두 쿼리가 논리적으로 동등한 지 여부는 관련이 없습니다. 당신은 그들 중 하나를 사용해서는 안됩니다. 나는 당신을 몇 가지 것들로부터 멀어지게하려고 노력할 것입니다 :

  1. 가능하면 함수를 열에 적용하지 마십시오. 열이 아닌 상수에 대해 계산을 유지하는 것이 항상 좋으며 대부분 더 좋습니다. 이는 SARGability를 파괴하고 해당 열의 인덱스를 쓸모 없게 만들 수 있습니다. 이 경우 쿼리 2를 선호합니다. 특히LogDateTime 색인이 생성 된 경우 (또는 가능할 수도 있음).
  2. 나는 속기 수학을 좋아하지 않으며 그것을 반대하는 것이 좋습니다. 물론 입력하는 것이 더 빠르지 만 DATE데이터 유형으로 시도 하면 추악한 오류가 발생합니다. 철자를 쓰는 것이 훨씬 낫습니다. 예 :

    WHERE LogInsertTime < DATEADD(DAY, -7, @DateTime);

내 목표는 쿼리 1을 쿼리 2와 비슷한 것으로 변경하여 인덱스를 효과적으로 사용할 수 있다는 데 동의합니다. 도와 주셔서 감사합니다
Alf47

8

다음과 같은 sargeable 쿼리를 사용합니다.

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

이유 : @ DateTime-7의 결과가 문서화되어 있지 않다고 생각합니다. DATEADD (DAY, -7, @DateTime)와 동일하더라도 이후 릴리스에서 중단 될 수 있습니다.


그것이 바로 내가 찾던 것입니다. 감사합니다
Alf47

2
그것은 사실이다 문서화하고 잘 정의 : - (Subtract): Subtracts two numbers (an arithmetic subtraction operator). Can also subtract a number, in days, from a date.. 그럼에도 불구하고, 명시적인 날짜 함수를 사용하면 결과 산술이 "산술 연산자 마법"보다 더 읽기 쉽고 유지 관리 가능하다는 데 동의합니다.
Heinzi

6

그것들은 동등하지 않습니다. 7 일 전이지만 현재 시간 이전 인 레코드 는 쿼리 # 2에서만 반환됩니다.

사용하여 일을 비교할 때 DATEADD기능을 , 그것은 고려하여 시간 부분을 고려하지 않습니다 . 시간에 관계없이 일요일과 월요일을 비교할 때 함수는 1을 리턴합니다.

데모:

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.

잠재적 인 인덱스 사용을 가능하게하는 첫 번째 쿼리와 논리적으로 동등한 부분은 시간 부분을 제거 @DateTime하거나 시간을 0:00:00다음과 같이 설정하는 것입니다 .

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

첫 번째 쿼리에서 인덱스를 사용할 수없는 LogInsertTime이유는 열이 함수 내에 묻혀 있기 때문입니다. 쿼리 # 2는 열을 상수 값과 비교하여 옵티마이 저가에서 인덱스를 선택할 수있게합니다 LogInsertTime.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.