Цикл не зацикливается на generate_series - PullRequest
0 голосов
/ 02 января 2019

Я создаю функцию plpgsql для заполнения таблицы поиска для получения информации о дате.Мой оператор цикла выполняет только первую дату, он не зацикливается на дополнительные дни.

  DECLARE
startDate ALIAS FOR $1;
endDate ALIAS FOR $2;
currentDate date;
dateDate integer;
yearDate integer;
monthDate integer;
dayDate integer;
weekDate integer;
dayofWeekDate integer;
weekofYearDate integer;
quarterDate integer;

BEGIN
DELETE FROM date_data;

FOR currentDate IN (SELECT * FROM generate_series(startDate::date,endDate::date,'1 day') s(currentDate)) LOOP
    yearDate := (SELECT date_part('year', currentDate));
    monthDate := (SELECT date_part('month', currentDate));
    dayDate := (SELECT date_part('day', currentDate));
    weekDate := (SELECT date_part('week', currentDate));
    dayofWeekDate := (SELECT date_part('dow', currentDate));
    quarterDate := (SELECT date_part('quarter', currentDate));
    weekofYearDate := (SELECT date_part('week', currentDate));
    dateDate := to_char(currentDate,'YYYYMMDD');

    INSERT INTO date_data VALUES ( dateDate, yearDate, monthDate, dayDate, FALSE, dayofWeekDate, FALSE, NULL, FALSE, NULL, weekofYearDate, quarterDate);

    RETURN dateDate;
END LOOP;
END;

Я ожидаю, что он будет циклически проходить во временных рядах, вставляя ожидаемые значения, однако он только вставляетпервая дата и не продолжается.

Я вызываю функцию с помощью SELECT add_date_data2 ('2018-01-01', '2019-01-01');

Спасибо.

1 Ответ

0 голосов
/ 02 января 2019

в вашем коде используется множество анти-шаблонов, которые значительно снижают производительность

  1. цикл над запросом вместо цикла int

    FOR IN SELECT * FROM generate_series ..
    
  2. бесполезнозапросы в присваивании

    var := (SELECT expr)
    

Таким образом, ваш код может быть переписан на один SQL INSERT

INSERT INTO date_data
   SELECT to_char(d::date,'YYYYMMDD'),
          date_part('year', d::date),
          ...
     FROM generate_series(startdate::date, enddate::date, '1day') g(d);               

или очень классический:

WHILE d < enddate
LOOP
  yearDate := date_part('year', currentDate);
  monthDate := date_part('month', currentDate);
  dayDate := date_part('day', currentDate);

  INSERT INTO date_data VALUES ( dateDate, yearDate, monthDate, dayDate, FALSE ...
  d := d + interval '1day';
END LOOP;

Выражения оцениваются в 10 раз быстрее, чем те же функциональные запросы - поэтому используйте запросы только тогда, когда это необходимо - чем больше, ваш код будет намного более читабельным и чище.

...