문제

I am trying to update the datedelta field for each group of item codes. The datedelta field is supposed to contain the number of days since the last sale of a particular item. For example, my table looks like this prior to the update:

Table: 'sales'

   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

After the update, I would like the table to look like this:

   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

I'm having trouble with the following aspects:

a) how to do a self join and refer to the record with the previous date, and

b) how to handle the grouping part. i.e. the date difference is only to be calculated for the same itemcode.

I have tried the following query without success:

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)
도움이 되었습니까?

해결책

With questions of finding gaps in consecutive records I find it fun to use Cursors to iterate through the records. I don't see them used often here, but I think they are easier to wrap the head around than the sometime intricate self joins, etc.

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;

I haven't tested or debugged this, but this will roughly do it for you.

다른 팁

Although you can do this with a join, I find it easier to do with a correlated subquery:

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);

As for your query, at least one problem is that the table aliases used with the columns do not match the aliases defined for the tables.

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