전문가가되자
149
2019-08-13 14:16:20
9
205

sql문 질문잇습니다.



1. WHERE STARTEDDATE between to_date(#{FirstDate},'YYYY/MM/DD') AND to_date(#{LastDate},'YYYY/MM/DD')


2. WHERE TO_CHAR(STARTEDDATE,'YYYY/MM/DD') between #{FirstDate} AND #{LastDate}

이거 2개 차이가 혹시 많나요??

1번으로 햇더니 오늘 데이터를 생성하니깐 조회가 안되고 2번으로 하니깐 조회가 되서요... 혹시 다른점이잇나요..

0
0
  • 답변 9

  • dev_seya
    4
    2019-08-13 14:26:12

    STARTEDDATE 의 데이터 타입이 뭔지 모르겠는데 to_char는 캐릭터 셋이고 to_date는 date타입입니다. 아마도 to_char가 실행되는 것을 봐서는 뽑으려는 데이터가 문자일 가능성이 높겠네요

    0
  • 그만물어봐
    125
    2019-08-13 14:26:16 작성 2019-08-13 14:28:05 수정됨

    db가 어떻게 되는지 모르겠지만~

    STARTEDDATE 컬럼의 데이터 타입이 date 인가보군요?

    이렇게 되면 년, 월, 일, 시, 분, 초 까지 들어가게 됩니다.

    첫번째 쿼리에서 FirstDate 와 LastDate 아규먼트 값이 문자값으로 보이네요?

    그래서 to_date 사용해서 형변환을 하셨을 겁니다~

    이때 확실하지 않지만 시분초가 모두 00:00:00 이렇게 변환 될꺼에요~

    그렇다면 STARTEDATE 들어있는 시분초와 비교했을때

    시분초 조건이 맞지 않아 조회되지 않을 수 있습니다.


    두번째 쿼리 같은 경우


    TO_CHAR 를 이용해서 STARTDATE 를 문자 타입으로 형변화 하셨네요~

    이때 포맷을 YYYY/MM/DD 로 변화 했기 때문에 시분초가 포함이 안됬을 껍니다~

    이때는 시분초를 비교하지 않으므로 조건에 맞게 조회될 수 있겠네요~

    0
  • 0
  • 그만물어봐
    125
    2019-08-13 14:35:45

    화이팅 입니다!!

    0
  • 제타건담
    6k
    2019-08-13 14:46:35 작성 2019-08-13 14:48:26 수정됨

    STARTEDDATE 컬럼에 인덱스가 걸려있을 경우엔 첫번째 방법으로 해야 합니다..

    인덱스가 걸려있는 컬럼에 형변환이 적용되면 인덱스를 적용하지 않기 때문에 검색속도가 떨어집니다..

    그래서 그럴때는 lastdate를 자바단에서 date로 변환한뒤 하루를 더 더한뒤 다시 YYYY/MM/DD 포맷으로 String 으로 변환한뒤

    between이 아니라 STARTEDDATE >= to_date(#{FirstDate},'YYYY/MM/DD')  AND STARTEDDATE < to_date(#{LastDate}, 'YYYY/MM/DD') 로 하시면 됩니다..

    lastdate를 하루를 더 더한상태이기 때문에 시분초가 00:00:00으로 셋팅이 되어도 작은것을 검색하도록 했기 때문에 그 이전날의 모든 시간이 다 포함됩니다..

    0
  • 0
  • 그만물어봐
    125
    2019-08-13 15:31:25
    0
  • 제타건담
    6k
    2019-08-13 15:42:47 작성 2019-08-13 15:44:50 수정됨

    DB 관련 책이나 검색을 해보면 아실수 있는 내용인데..대략적으로 설명을 하자면..

    관련 레코드에 직접적으로 접근할 수 있는 주소를 저장한다고 보시면 됩니다..

    흔히 우리가 사용하는 primary key도 내부적으로는 unique index로 구현되어 있는겁니다..

    애초에 질문을 starteddate 컬럼으로 하셨으니 이걸로 구체적인 예를 들어보일께요..

    테이블에 4개의 레코드가 있는데 각 레코드는 디스크 주소로 110, 120, 130, 140 번지를 이용한다고 가정해보죠..

    그리고 110번지의 레코드에는 starteddate 컬럼이 '2019-05-07', 120 번지의 레코드에는 starteddate 컬럼이 '2019-08-02', 130 번지에는 starteddate 컬럼이 '2019-07-02', 140 번지의 레코드에는 starteddate 컬럼이 '2019-05-09' 이렇게 저장되어 있다고 가정해보고..


    이제 다음과 같이 조건을 주죠..

    where starteddate between '2019-05-01' and '2019-05-31'


    만약 starteddate 컬럼에 인덱스가 걸려있지 않을 경우 DB는 해당 레코드를 찾기 위해 110번지부터 140번지까지 모두 검색해야 합니다..

    그러나 만약 다음과 같이 starteddate 컬럼을 오름차순으로 인덱스를 만든다면..DB는 내부적으로 다음과 같은 내용을 만들어둡니다..

    '2019-05-07'  110

    '2019-05-09'  140

    '2019-07-02'  130

    '2019-08-02'   120


    이렇게 starteddate 컬림의 값에 해당 하는 레코드의 주소를 같이 저장합니다. 그러면 다시 위와 같은 조건을 주어 검색할때 어떻게 하게 되냐면 테이블을 먼저 뒤지는 것이 아니라 인덱스를 먼저 뒤져서 해당 값을 만족하는 레코드 주소를 먼저 찾은뒤 그 주소를 바로 접근하게 됩니다..즉 테이블을 첨부터 끝까지 뒤져서 찾는게 아니라 조건을 만족하는 값을 먼저 인덱스에서 찾아 이에 대한 주소로 바로바로 접근하기 때문에 검색속도에 있어서는 훨씬 빠르게 되는거죠..


    그러나 조건을 줄때 이렇게 인덱스가 걸려있는 컬럼을 가공하게 되면 애초에 인덱스에 저장되어 있는 값은 가공된 값이 아니기 때문에 인덱스를 이용하지 않고 일일이 디스크를 뒤져가며 해당 컬럼을 가공해서 비교하게 되기 때문에 속도가 느려지게 됩니다..


    이것도 분포도까지 얘기하게 되면 너무 내용이 깊어지니까 일단은 개념에 대한 설명으로 이정도선까지만 얘기할께요..어떤 DB든 인덱스는 다 구현해서 사용하고 있습니다 그러니까 SQL 관련 책을 하나 사서 공부를 하시면 도움이 될꺼에요..

    0
  • 전문가가되자
    149
    2019-08-13 16:34:22

    그만물어봐, 제타건담

    : 수정으로 다시 찾아봐서 감사하다고 올렷는대 적용이안됫나보네요...ㅠㅠㅠㅠㅠㅠㅠ

    정말감사합니다.

    글올리고 인덱스 검색해서 찾아보고 다시 댓글 수정햇는대ㅠㅠㅠㅠㅠ

    정말감사합니다.

    0
  • 로그인을 하시면 답변을 등록할 수 있습니다.