문제

백만 개 이상의 레코드가 포함된 큰 테이블이 있습니다.불행하게도 테이블을 만든 사람은 날짜를 varchar(50) 필드.

간단한 날짜 비교를 해야 합니다.

datediff(dd, convert(datetime, lastUpdate, 100), getDate()) < 31

그러나 그것은 실패합니다 convert():

Conversion failed when converting datetime from character string.

아무래도 그 분야에 마음에 들지 않는 부분이 있는 것 같은데, 기록이 너무 많아서 겉으로는 알 수가 없어요.전체 날짜 필드를 적절하게 삭제하여 날짜에 오류가 발생하지 않도록 하려면 어떻게 해야 합니까? convert()?내가 지금 가지고 있는 것은 다음과 같습니다.

select count(*)
from MyTable
where
    isdate(lastUpdate) > 0
    and datediff(dd, convert(datetime, lastUpdate, 100), getDate()) < 31

@SQL메나스

이 경우 성능에 대해서는 걱정하지 않습니다.이것은 일회성 쿼리가 될 것입니다.테이블을 날짜/시간 필드로 변경하는 것은 옵션이 아닙니다.

@존 림잡

세 번째 인수를 추가해 보았지만 아무런 차이가 없습니다.


@SQL메나스

문제는 데이터가 저장되는 방식일 가능성이 높습니다. 안전한 형식은 두 가지뿐입니다.ISO YYYYMMDD;ISO 8601 yyyy-mm-dd Thh:mm:ss:mmm(공백 없음)

그렇지 않겠습니까? isdate() 확인해 보세요. 이것 좀 처리해 주시겠어요?

100% 정확도는 필요하지 않습니다.지난 30일 동안의 대부분의 기록을 가져오고 싶습니다.


@SQL메나스

select isdate('20080131') -- returns 1
select isdate('01312008') -- returns 0

@브라이언 슈케르케

CASE와 ISDATE를 CONVERT() 함수 안에 넣습니다.

감사해요!그랬어요.

도움이 되었습니까?

해결책

두는 CASE 그리고 ISDATE 안에 CONVERT() 기능.

SELECT COUNT(*) FROM MyTable
WHERE
    DATEDIFF(dd, CONVERT(DATETIME, CASE IsDate(lastUpdate)
        WHEN 1 THEN lastUpdate
        ELSE '12-30-1899'
    END), GetDate()) < 31

바꾸다 '12-30-1899' 선택한 기본 날짜로.

다른 팁

내용을 반복하는 커서를 작성하여 각 항목에 대해 캐스트를 시도하는 것은 어떻습니까? 오류가 발생하면 문제 기록에 대한 기본 키 또는 기타 식별 세부 정보를 출력합니다.나는 이것을 수행하는 세트 기반 방법을 생각할 수 없습니다.

완전히 설정되지는 않았지만 100만 개 중 3개 행만 잘못된 경우 많은 시간을 절약할 수 있습니다.

select * into BadDates
from Yourtable
where isdate(lastUpdate) = 0

select * into GoodDates
from Yourtable
where isdate(lastUpdate) = 1

그런 다음 BadDates 테이블을 보고 수정하세요.

ISDATE()는 실제로 먼저 실행되는 경우 제대로 형식화되지 않은 행을 처리합니다.그러나 실행 계획을 살펴보면 DATEDIFF 조건자가 먼저 적용되어 고통의 원인이 된다는 것을 알 수 있습니다.

SQL Server Management Studio 히트를 사용하는 경우 CTRL 키+ 특정 쿼리에 대한 예상 실행 계획을 보려면

SQL은 절차적 언어가 아니며 단락 논리가 작동할 수 있지만 적용 방법에 주의를 기울인 경우에만 작동할 수 있습니다.

각 항목에 대해 캐스트를 시도하면서 내용을 반복하는 커서를 작성하는 것은 어떻습니까?

오류가 발생하면 문제 기록에 대한 기본 키 또는 기타 식별 세부 정보를 출력합니다.

나는 이것을 수행하는 세트 기반 방법을 생각할 수 없습니다.

편집하다 - 아 네, ISDATE()를 잊어버렸어요.커서를 사용하는 것보다 확실히 더 나은 접근 방식입니다.SQLMenace에 +1.

변환 호출에서는 세 번째 스타일 매개변수(예: 이 문서에 지정된 대로 varchar로 저장되는 날짜/시간 형식)를 지정해야 합니다. CAST 및 CONVERT(T-SQL)

기록을 인쇄하세요.varchar(50)을 사용하기로 결정한 바보에게 하드카피를 주고 문제 기록을 찾아보라고 요청하세요.

다음번에는 적절한 데이터 유형을 선택하는 요점을 알게 될 것입니다.

문제는 데이터가 저장되는 방식일 가능성이 높습니다. 안전한 형식은 두 가지뿐입니다.

ISO YYYYMMDD

ISO 8601 yyyy-mm-dd Thh:mm:ss:mmm(공백 없음)

이는 귀하의 언어가 무엇이든 상관없이 작동합니다.

작동하려면 SET DATEFORMAT YMD(또는 데이터가 저장되는 형식)를 수행해야 할 수도 있습니다.

isdate() 검사가 이 문제를 처리하지 않을까요?

이것을 실행하여 무슨 일이 일어나는지 확인하십시오.

select isdate('20080131')
select isdate('01312008')

레거시 시스템 요구 사항으로 인해 테이블/열을 변경하는 것이 옵션이 아닐 수도 있지만 최신 버전의 SQL을 사용하는 경우 날짜 변환 논리가 내장된 뷰를 만드는 것에 대해 생각해 보셨나요? 인덱싱된 뷰를 사용할 수도 있나요?

이런 일을 하기 때문에 혼란을 정리하고 열을 날짜/시간으로 변경하는 것이 좋습니다.

WHERE datediff(dd, convert(datetime, lastUpdate), getDate()) < 31

인덱스를 사용할 수 없으며 날짜/시간 열이 있는 경우보다 몇 배 더 느려질 것입니다.

where lastUpdate > getDate() -31

물론 시간과 초도 고려해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top