2013-08-13 2 views
1

각 항목 코드 그룹에 대해 datedelta 필드를 업데이트하려고합니다. datedelta 필드는 특정 항목의 마지막 판매 이후 일수를 포함해야합니다.이전 행의 값과 그룹을 사용하여 UPDATE 쿼리

테이블 : : 업데이트 후 '판매'

id  date  datedelta itemcode 
    -------------------------------------------- 
    1 2012-09-01  null   1 
    2 2012-09-08  null   1 
    3 2012-09-20  null   1 
    4 2012-03-01  null   2 
    5 2013-06-01  null   3 
    6 2013-06-06  null   3 

, 나는 다음과 같이하기 위해 테이블을 싶습니다

id  date  datedelta itemcode 
    -------------------------------------------- 
    1 2012-09-01  0   1 
    2 2012-09-08  7   1 
    3 2012-09-20  12   1 
    4 2012-03-01  0   2 
    5 2013-06-01  0   3 
    6 2013-06-06  5   3 

예를 들어, 내 표는 같은이 업데이트 이전에 보인다 다음과 같은 측면에 문제가 있습니다.

a) 자체 가입을 수행하고 이전 날짜의 레코드를 참조하는 방법 및

b) 그룹화 부분을 처리하는 방법. 즉, 날짜 차이는 동일한 항목 코드에 대해서만 계산되어야합니다.

나는 성공없이 다음 쿼리를 시도 :

UPDATE sales AS s 
INNER JOIN sales AS prev 
ON prev.id IN (SELECT t.id FROM sales WHERE MAX(t.saledate) < r.saledate GROUP BY itemcode ORDER BY itemcode) 
SET datedelta = IFNULL(DATEDIFF(r.saledate, p.saledate), 0) 

답변

0

연속 된 레코드에서 간격을 찾는 질문으로 커서를 사용하여 레코드를 반복하는 것이 재미 있다는 것을 알게되었습니다. 나는 그들이 여기 자주 사용 표시되지 않습니다,하지만 난 등

CREATE PROCEDURE findgaps() 
    BEGIN  

    DECLARE done INT DEFAULT FALSE; 
    DECLARE idv, datedeltav, itemcodev, prev_itemcodev INT; 
    DECLARE datev, prev_datev DATE; 

    DECLARE cur CURSOR FOR SELECT id, date, datedelta, itemcode 
          FROM sales 
          ORDER BY itemcode ASC, date ASC; 

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 

    OPEN cur;  

    read_loop: LOOP 
     SET prev_datev = datev; 
     SET prev_itemcodev = itemcodev; 
     FETCH cur INTO idv, datev, datedeltav, itemcodev; 
     IF done THEN 
      LEAVE read_loop; 
     END IF; 
     IF NOT itemcodev <=> prev_itemcodev THEN 
      SET prev_datev = datev; 
     END IF; 
     UPDATE sales s 
     SET s.datedelta = DATEDIFF(datev,prev_datev) 
     WHERE s.id = idv; 
    END LOOP;  

    CLOSE cur; 

    END; 

내가 테스트하거나 디버깅하지 않은, 그들은 언젠가 복잡한 자체 조인보다 주위에 머리를 정리하고 쉽게 생각하지만, 이것은 대략 것 너를 위해서해라.

+0

감사합니다. Alden. 필자는 mysql 커서에 익숙하지 않지만 필수적인 업데이트가 더욱 복잡 해지면 강력한 솔루션처럼 보입니다. – Jason

0

당신은 내가 쉽게 상관 하위 쿼리와 함께 할 찾아 가입하여이 작업을 수행 할 수 있지만 : 관해서

UPDATE sales s 
    set s.datedelta = coalesce(datediff((select sprev.racedate 
              from sales sprev 
              where sprev.itemcode = s.itemcode and 
               sprev.racedate < s.racedate 
              order by sprev.racedate desc 
              limit 1 
             ), rprev.racedate 
             ), 0); 

당신의 쿼리에서 적어도 하나의 문제는 열과 함께 사용 된 테이블 별칭이 테이블에 대해 정의 된 별칭과 일치하지 않는다는 것입니다.

+0

고든에게 감사드립니다. 일치하지 않는 별칭에 대해 죄송합니다. 나는 현실 세계의 문제를 질문 예제로 올바르게 번역하지 않았다. 당신의 솔루션은 잘 작동하는데, 중요한 변경은 MYSQL 에러를 피하기 위해 서브 쿼리에서 다른 SELECT 문을 사용하는 것입니다 : "FROM 절에서 업데이트를 위해 목표 테이블의 '을 지정할 수 없습니다." 세트 s.datedelta = 유착이 가 \t ( 행을 선택 sprev.date (DATEDIFF (s.date, s 정도 (AS), (C) AS 영업 c.itemcode을 c.date을 선택 UPDATE 판매 : – Jason

+0

개정 코드 같다 sprev 여기서 sprev.itemcode = s.itemcode 및 sprev.date Jason

+0

문제는 이제 쿼리를 실행하는 데 걸리는 시간입니다. 실제 테이블에는 1 백만 개가 넘는 레코드가 있습니다. itemcode에 대한 인덱스와 date에 대한 인덱스를 만들었고 쿼리를 완료하는 데 15 분 이상이 걸렸습니다 (이후에 서버를 다시 시작하여 중지했습니다). 이 쿼리를 빠르게하기위한 아이디어가 있습니까? – Jason