Q&A

  • [질문 : 날짜계산 SQL] 현재부터 3개월 이전 데이타를 DBGrid 에 출력하려 합니다.
안녕하세요? 새배 복 많이 받으세요. ^^

또 한번 고수님들께 도움을 요청합니다.

DB에 있는 데이타들을 임의의 특정시점 (예를 들어서 오늘)에 검색을 하여 3개월 이전의 데이타는 모두 삭제를 하도록 하려고 합니다. (데이타 저장기간을 3개월로 하려고 합니다)
그런데 SQL 을 어떻게 날려야 할지 난감해서 도움을 요청해봅니다.

DB : SQL 서버
Table 명 : visit
----------------------------------------------------------
    visitDate : datetime
    phone     : nVarchar(12)
    name      : nVarchar(30)
    type        : nchar (4)
    point1     : numeric(5,1)
    point2     : numeric(5,1)
----------------------------------------------------------

Form 에 DBGrid 를 놓고, point1 과 point2가 5 미만이면서,  현재부터 3개월 이전의 모든 데이타를 출력해서 Button1 을 누르면 해당 데이타를 모두 삭제하려는 프로그램을 만들어 보려고 하는데..

procedure TFrm_erase.FormActivate(Sender: TObject);
var
   wDate : TDateTime;
begin
  wDate := date - 90   //3개월 전을 어떻게 표현할지 몰라서 대략 90일로 써본 거에요
  with Qry_erase do
    begin
      close;
      SQL.Clear;
      SQL.Add('select phone, name, point1, point2, visitDate from visit ');
      SQL.Add('where ((point1 < 5) and (visitDate < :date)) or
                       ((point2 < 5) and (visitDate < :date))');
      Parameters[0].Value := wDate;
      open;
    end;
end;


뭐 이런 식으로 해봤는데.. 아무것도 나오지도 않는군요..  날짜계산을 저렇게 하는 것이 맞는 것인지...
이래저래 검색하다가 비슷해 보이길래 파라미터값을 저런 식으로 넣어봤는데 맞는 건지 모르겠네요.
그리고 where 절에서 날짜를 부등호로 비교를 하는 것이 맞는 건가요?

고수님들의 가르침을 기다리겠습니다.

P.S 컴파일 에러도 안나고 데이타는 안나오고 해서 영문을 모르겠습니다. ㅎㅎ;;;
      참고로 델파이 7 사용하고 있고, ADO 로 MSSQL 서버를 연결해서 사용하고 있습니다.
4  COMMENTS
  • Profile
    홍성락 2009.01.09 18:40
    DB 쿼리보다는 상황을 모르겠수요, 날짜계산 예를 적어봅니다
    <!--CodeS-->
    //현재로 부터 3개월전
    function Now_3Month:TDateTime;
    var
    Year, Month, Day: Word;
    DayTable: PDayTable;
    begin
    Result := now;
    //현재를 년월일로 만듭니다
    DecodeDate(now, Year, Month, Day);
    //현재를 월에서 3개월전 (주의) Year, Month, Day변수 형식이 Word라서 음수계산이 안됩니다
    if Month -3 < 1 then Month := 12 + (Month -3)
    else Month := Month -3;
    //년월이 맞는지 1차검사
    if (Year >= 1) and (Year <= 9999) and (Month >= 1) and (Month <= 12) then begin
    //년월의 마직막 일자가 맞는지 2차검사, 년월의 마직막 일자 목록을 가져옵니다
    DayTable := @MonthDays[IsLeapYear(Year)];
    if (Day < 1) then Day := 1
    else if (Day > DayTable^[Month]) then Day := DayTable^[Month]; //년월의 마직막 일자가 넘으면 마직막 일자로함

    Result := EncodeDate(Year, Month, Day); //3개월전....
    end;
    end;

    <!--CodeE-->
  • Profile
    델파이쌩초보 2009.01.09 21:11

    성락님 관심을 가져 주셔서 대단히 감사합니다.

    일단 상황 자체는 회원테이블에 회원등록을 한 후에 point1, point2 의 두가지 점수관리를 하는 프로그램인데 점수가 5미만인 것에 대해서만, 마지막으로 insert 된 날짜로부터 3개월이 지나면 회원의 점수를 0으로 초기화시키려고 합니다. 자동으로 3개월이 지나면 초기화 되면 좋겠지만, 지금은 실력이 너무 딸려서 엄두는 못내고 일단은 아무때나 수동으로 검색해서 해당 리스트를 확인하여 초기화 시키려고 합니다.

    ㅎㅎ 복잡한 함수가 있었군요.(지금부터 성락님 코드를 열심히 공부해야겠어요..감사해요)

    이것도 한번 봐주시겠습니까? 어제 리플이 바로 안달려서 그냥 편법으로 해 본건데.. 일단 데이타는 나오기는 하는데 맞는 건지는 모르겠군요.
    (델파이에서 어떻게 처리하는지 몰라서 그냥 SQL로만.. ;;;)

    procedure TFrm_erase.FormActivate(Sender: TObject);

    begin
    with Qry_erase do
    begin
    close;
    SQL.Clear;
    SQL.Add('select phone, name, point1, point2, visitDate from visit ');
    SQL.Add('where ((point1 < 5) and (datediff(month, visitDate, current_timestamp) > 3)) or
    ((point2 < 5) and (datediff(month, visitDate, current_timestamp) > 3))');
    open;
    end;
    end;

    MSSQL 도움말을 뒤지다 보니 datediff 라는 함수가 있더군요. 그래서 한번 써보기는 했는데..
    지금은 view Table 을 하나 만들고 필드를 만들어서 datediff 로 수식을 줘봤습니다.
    아직은 데이타가 많이 없어서 그냥저냥 속도가 나오기는 하는데..

    성락님이 알려주신대로 델파이에서 처리를 하는 것이 처리속도가 빠를까요? 아니면 SQL 로 날려서 결과를 받는 것이 처리속도가 빠를까요?

    일단은 제가 만든 SQL 코드가 맞는지부터 자신이 없으니.. ㅎㅎ

    어쨋든 너무너무 감사하고요, 역시 고수는 뭐가 달라도 다르다는 느낌을 또 한번 가져봅니다. ^^
  • Profile
    홍성락 2009.01.09 22:11
    위와 같이 필드가 적은 경우 SQL 문은 맞는거 같구요.
    SQL 문으로 처리하는게 좋죠. 그런데 같은 계산인 datediff로 처리하는게 2번이네요. and 조건을 괄호 밖으로 빼세요.
    제가 쓴 델파이처리는 나중에 패치로 사용하실때 응용해 보세요.
    저 같은경우는 DB의 함수를 왠만하면 잘 안써요, 데이타베이스 종류에 따라 좀 다른 함수/문법등에 의해 데이타베이스 자체를 바꾸는경우를 대비...또는 그냥 범용적으로...
    그런데 SQL잘하시는분은 한줄에 처리할 수 있다고 자랑?(속도는 솔직히 DB구조에 따라 다른데...)
  • Profile
    델파이쌩초보 2009.01.09 22:58

    아 그런 경우도 있겠군요.

    디비를 바꿀 경우는 다시 새롭게 다 코딩을 해야할 수 있겠군요. 역시.. ^^
    감사합니다.

    코딩 경험이 거의 없기도 하거니와 로직의 이해도도 낮아서 지금은 이것저것 생각할 여유도 없네요..ㅎ;;;
    친절한 고수님들이 있기에 많이 배우고 있습니다.