Как правильно передать параметр из функции-оболочки во вложенную функцию кросс-таблицы? Проблема - PullRequest
0 голосов
/ 03 августа 2020

Я хочу передать свой параметр input_date из моей функции-оболочки в запрос во вложенной сигнатуре перекрестной таблицы. Но у меня ОШИБКА. Что я делаю не так в предложении BETWEEN?

ОШИБКА

SQL Error [42725]: ERROR: function date_trunc(unknown, unknown) is not unique
  Hint: Could not choose a best candidate function. You might need to add explicit type casts.
  Where: PL/pgSQL function get_week_report(date) line 3 at RETURN QUERY

SQL код

CREATE OR REPLACE FUNCTION get_week_report(input_date date)
  RETURNS TABLE (office_id int, Mon int, Tue int, Wed int, Thu int, Fri int, Sat int, Sun int, Total int) AS
$BODY$
BEGIN
    RETURN QUERY
    SELECT * 
    FROM crosstab(
        $$WITH cte AS(
            SELECT mcio.office_id, 
                   EXTRACT(isodow FROM rmcs.rented_at) AS week_day, 
                   COUNT(*) AS rented_movies 
            FROM movie_copy_in_office AS mcio 
                 INNER JOIN rented_movie_copy_status AS rmcs 
                 ON mcio.id = rmcs.id_movie_copy_in_office 
                   AND rmcs.rented_at::date 
                     BETWEEN date_trunc('week', $$ || quote_literal(input_date) || $$)::date AND 
                             date_trunc('week', $$ || quote_literal(input_date) || $$)::date + INTERVAL '6 days' 
            GROUP BY 1, 2
            )
          TABLE cte
          UNION ALL
          SELECT office_id, 999 AS week_day, SUM(rented_movies) AS rented_movies
          FROM cte
          GROUP BY 1
          ORDER BY 1$$,
        $$VALUES (1), (2), (3), (4), (5), (6), (7), (999)$$
    ) AS (office_id int, 
          "Mon" int, 
          "Tue" int, 
          "Wed" int, 
          "Thu" int, 
          "Fri" int, 
          "Sat" int, 
          "Sun" int, 
          "Total" int);
END
$BODY$ 
LANGUAGE plpgsql;

PS Обратите внимание, что кросс-таблица отлично работает с переменной input_date и без предложения BETWEEN.

1 Ответ

0 голосов
/ 04 августа 2020

Решение оказалось простым.

Просто нужно вычислить даты и присвоить их переменным (start_week_date, end_week_date). А затем используйте переменные в предложении BETWEEN.

CREATE OR REPLACE FUNCTION get_week_report(input_date DATE)
  RETURNS TABLE (office_id int, Mon int, Tue int, Wed int, Thu int, Fri int, Sat int, Sun int, Total int) AS
$BODY$
DECLARE
    start_week_date DATE := DATE_TRUNC('week', input_date)::DATE;
    end_week_date DATE := DATE_TRUNC('week', input_date)::DATE + INTERVAL '6 days';
BEGIN
    RETURN QUERY
    SELECT * 
    FROM crosstab(
        $$WITH cte AS(
            SELECT mcio.office_id, 
                   EXTRACT(isodow FROM rmcs.rented_at) AS week_day, 
                   COUNT(*) AS rented_movies 
            FROM movie_copy_in_office AS mcio 
                 INNER JOIN rented_movie_copy_status AS rmcs 
                 ON mcio.id = rmcs.id_movie_copy_in_office 
                   AND rmcs.rented_at::DATE 
                     BETWEEN $$ || QUOTE_LITERAL(start_week_date) || $$ AND $$ || QUOTE_LITERAL(end_week_date) ||
            $$GROUP BY 1, 2
            )
          TABLE cte
          UNION ALL
          SELECT office_id, 999 AS week_day, SUM(rented_movies) AS rented_movies
          FROM cte
          GROUP BY 1
          ORDER BY 1$$,
        $$VALUES (1), (2), (3), (4), (5), (6), (7), (999)$$ -- 999 is 'Total'
    ) AS (office_id int, 
          "Mon" int, 
          "Tue" int, 
          "Wed" int, 
          "Thu" int, 
          "Fri" int, 
          "Sat" int, 
          "Sun" int, 
          "Total" int);
END
$BODY$ 
LANGUAGE plpgsql;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...