쿼리 - sqlite 날짜 검색




TSQL에서 두 날짜 시간이 같은 요일에 있는지 확인하는 좋은 방법은 무엇입니까? (7)

여기에 내가 가지고있는 문제는 다음과 같습니다. 두 날짜가 같은 날인지 확인하기 위해 where 절의 datetimes를 비교해야하는 큰 쿼리가 있습니다. 내 현재 솔루션은 짜증나는데, datetimes를 UDF로 보내어 같은 날 자정으로 변환 한 다음 그 날짜가 동일한 지 확인합니다. 쿼리 계획의 경우 이것은 조인 또는 where 절의 거의 모든 UDF와 마찬가지로 재앙입니다. 이것은 응용 프로그램에서 함수를 뿌리 뽑을 수 없었고 쿼리 최적화 프로그램에 최상의 인덱스를 찾는 데 실제로 사용할 수있는 무언가를 제공하지 못하는 유일한 장소 중 하나입니다.

이 경우 함수 코드를 다시 쿼리와 병합하면 실용적이지 않습니다.

나는 여기서 간단한 것을 놓치고 있다고 생각한다.

다음은 참조 용 함수입니다.

if not exists (select * from dbo.sysobjects 
              where id = object_id(N'dbo.f_MakeDate') and               
              type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
  exec('create function dbo.f_MakeDate() returns int as 
         begin declare @retval int return @retval end')
go

alter function dbo.f_MakeDate
(
    @Day datetime, 
    @Hour int, 
    @Minute int
)
returns datetime
as

/*

Creates a datetime using the year-month-day portion of @Day, and the 
@Hour and @Minute provided

*/

begin

declare @retval datetime
set @retval = cast(
    cast(datepart(m, @Day) as varchar(2)) + 
    '/' + 
    cast(datepart(d, @Day) as varchar(2)) + 
    '/' + 
    cast(datepart(yyyy, @Day) as varchar(4)) + 
    ' ' + 
    cast(@Hour as varchar(2)) + 
    ':' + 
    cast(@Minute as varchar(2)) as datetime)
return @retval
end

go

문제를 복잡하게하기 위해 모든 시간대마다 다를 수있는 현지 시간과 날짜를 비교하기 위해 시간대 테이블에 가입했습니다.

where 
dbo.f_MakeDate(dateadd(hh, tz.Offset + 
    case when ds.LocalTimeZone is not null 
    then 1 else 0 end, t.TheDateINeedToCheck), 0, 0) = @activityDateMidnight

[편집하다]

나는 Todd의 제안을 반영하고있다.

where datediff(day, dateadd(hh, tz.Offset + 
    case when ds.LocalTimeZone is not null 
    then 1 else 0 end, t.TheDateINeedToCheck), @ActivityDate) = 0

데이트 테프가 어떻게 작동하는지에 대한 나의 오해 (내가 예상했던 것처럼 연중 계속되는 연중 같은 날은 0이 아닌 366을 산출한다) 때문에 많은 노력을 낭비하게되었다.

그러나 쿼리 계획은 변경되지 않았습니다. 나는 모든 것을 가지고 드로잉 보드로 돌아갈 필요가 있다고 생각한다.


datepart의 dayofyear 함수를 사용합니다.


Select *
from mytable
where datepart(dy,date1) = datepart(dy,date2)
and
year(date1) = year(date2) --assuming you want the same year too

여기 datepart 참조를 참조 하십시오 .


그러면 날짜에서 시간 구성 요소가 제거됩니다.

select dateadd(d, datediff(d, 0, current_timestamp), 0)

당신은 여기 옵션의 관점에서 선택의 여지가있다. Sybase 또는 SQL Server 2008을 사용하는 경우 date 유형의 변수를 만들고 datetime 값을 할당 할 수 있습니다. 데이터베이스 엔진은 시간을 없애줍니다. 다음은 설명하기에 빠르고 쉬운 테스트입니다 (Sybase Dialect에있는 코드입니다).

declare @date1 date
declare @date2 date
set @date1='2008-1-1 10:00'
set @date2='2008-1-1 22:00'
if @date1[email protected]date2
    print 'Equal'
else
    print 'Not equal'

SQL 2005 이전 버전에서는 시간 구성 요소가없는 형식으로 날짜를 varchar로 변환 할 수 있습니다. 예를 들어, 다음은 2008.08.22를 반환합니다.

select convert(varchar,'2008-08-22 18:11:14.133',102)

102 부분은 형식을 지정합니다 (온라인 설명서는 사용 가능한 모든 형식을 나열 할 수 있음)

따라서 datetime을 취하고 날짜 요소를 추출하고 시간을 버리는 함수를 작성하면됩니다. 이렇게 :

create function MakeDate (@InputDate datetime) returns datetime as
begin
    return cast(convert(varchar,@InputDate,102) as datetime);
end

그런 다음 동반자를위한 함수를 사용할 수 있습니다.

Select * from Orders where dbo.MakeDate(OrderDate) = dbo.MakeDate(DeliveryDate)

시간대와 관련하여, 단일 시간대 (모든 시간대는 UTC가 바람직 함)에 모든 날짜를 저장해야합니다. 어쨌든, 나는 datediff, datepart 및 다른 내장 된 날짜 함수를 사용하는 대답이 최선이라고 생각한다.



이것은 훨씬 간결합니다.

where 
  datediff(day, date1, date2) = 0

에릭 Z 비어드 :

활동 날짜는 현지 시간대를 나타내지 만 특정 시간대는 표시하지 않습니다.

알았어. 다시 드로잉 보드에. 이 시도:

where t.TheDateINeedToCheck BETWEEN (
    dateadd(hh, (tz.Offset + ISNULL(ds.LocalTimeZone, 0)) * -1, @ActivityDate)
    AND
    dateadd(hh, (tz.Offset + ISNULL(ds.LocalTimeZone, 0)) * -1, (@ActivityDate + 1))
)

@ActivityDate를 현지 시간으로 변환하고 비교합니다. 인덱스를 사용할 수있는 가장 좋은 기회입니다. 제대로 작동하는지 잘 모르겠지만 시도해보고 쿼리 계획을 확인해야합니다.

다음 옵션은 인덱싱 된 TimelineedToCheck 를 로컬 시간으로 계산하여 인덱싱 된 뷰입니다. 다음으로 돌아갑니다.

where v.TheLocalDateINeedToCheck BETWEEN @ActivityDate AND (@ActivityDate + 1)

INSERT 및 UPDATE에 약간의 오버 헤드가 있지만 확실히 인덱스를 사용합니다.