子查询返回的多行用作表达式但仅在函数中
More than one row returned by a subquery used as an expression but only in function
当我使用一个函数时它给出了提到的错误,但是当单独使用相同的代码时它工作得很好。哪里出了问题?
Fiddle 函数:https://dbfiddle.uk/?rdbms=postgres_12&fiddle=c4b0c8a59d2bd851284ed624ab1c335d
摆弄干净select:https://dbfiddle.uk/?rdbms=postgres_12&fiddle=7ccca6c70061aff1f6c394815aa8e9b1
示例数据:
create table report
(report_day date,
tickets_no integer,
tickets_stake numeric,
promo_tickets_no integer,
promo_tickets_stake numeric,
group_id integer);
insert into report
values
('2020-07-20',12,569.6, 2, 44,1),
('2020-07-20',61,2000, 5, 260,2),
('2020-07-21',35,1244.2, 11, 250,1),
('2020-07-21',100,2500.5, 29, 575,2),
('2020-07-22',66,2511.8, 23, 670,1),
('2020-07-22',125,3358.2, 50, 990,2);
CREATE OR REPLACE FUNCTION report(arguments json)
RETURNS json AS
$BODY$
DECLARE
dateFrom date;
dateTo date;
selectedType integer;
BEGIN
dateFrom := cast(arguments->>'dateFrom' as date);
dateTo := cast(arguments->>'dateTo' as date);
selectedType := cast(arguments->>'selectedType' as integer);
RETURN (
WITH full_data as (
with tickets as (
select
report_day
, sum(tickets_no) as tickets_no
, sum(tickets_stake) as tickets_stake
FROM report
WHERE selectedType = 0
AND report_day between dateFrom and dateTo
GROUP BY 1)
, promo_tickets as (
select
report_day
, sum(promo_tickets_no) as promo_tickets_no
, sum(promo_tickets_stake) as promo_tickets_stake
FROM report
WHERE selectedType = 1
AND report_day between dateFrom and dateTo
GROUP BY 1)
select
t.report_day
, sum(coalesce(t.tickets_no,0) + coalesce(pt.promo_tickets_no,0)) as tickets_no
, sum(coalesce(t.tickets_stake,0) + coalesce(pt.promo_tickets_stake,0)) as tickets_no
FROM tickets t
LEFT JOIN promo_tickets pt on t.report_day = pt.report_day
GROUP BY 1
ORDER BY 1)
select row_to_json(full_data) from full_data
);
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
select * from report(json_build_object('dateFrom', '2020-07-20', 'dateTo', '2020-07-22','selectedType', 0 ))
因为您正试图从一个函数中 return 多行,而本应只 return 编辑一行。向您的函数添加一个参数,最好是一个主键列(我想 tickets_no
),例如
CREATE OR REPLACE FUNCTION report(arguments json, i_tickets_no int)
并将查询重写为
WITH full_data AS
(WITH tickets AS
(SELECT report_day,
SUM(tickets_no) AS tickets_no,
SUM(tickets_stake) AS tickets_stake
FROM report
WHERE selectedType = 0
AND report_day BETWEEN dateFrom AND dateTo
AND tickets_no = i_tickets_no
GROUP BY 1),
promo_tickets as
(select report_day,
SUM(promo_tickets_no) as promo_tickets_no,
SUM(promo_tickets_stake) as promo_tickets_stake
FROM report
WHERE selectedType = 1
AND report_day BETWEEN dateFrom AND dateTo
GROUP BY 1)
select t.report_day,
SUM(COALESCE(t.tickets_no, 0) + COALESCE(pt.promo_tickets_no, 0)) AS tickets_no,
SUM(COALESCE(t.tickets_stake, 0) +
COALESCE(pt.promo_tickets_stake, 0)) AS tickets_no
FROM tickets t
LEFT JOIN promo_tickets pt
ON t.report_day = pt.report_day
GROUP BY 1
ORDER BY 1)
并通过添加第二个参数来调用。
如果您希望您的函数像您的查询一样return 报告对象数组,请更改此部分:
select row_to_json(full_data) from full_data
要将行聚合到一个数组中:
select json_agg(row_to_json(full_data)) from full_data
如果你想让函数return多行,那么你需要做两个改变:
CREATE OR REPLACE FUNCTION report(arguments json)
RETURNS table (row_to_json json) AS
对于return
:
RETURN QUERY (
WITH full_data as (
已更新fiddle here.
当我使用一个函数时它给出了提到的错误,但是当单独使用相同的代码时它工作得很好。哪里出了问题?
Fiddle 函数:https://dbfiddle.uk/?rdbms=postgres_12&fiddle=c4b0c8a59d2bd851284ed624ab1c335d
摆弄干净select:https://dbfiddle.uk/?rdbms=postgres_12&fiddle=7ccca6c70061aff1f6c394815aa8e9b1
示例数据:
create table report
(report_day date,
tickets_no integer,
tickets_stake numeric,
promo_tickets_no integer,
promo_tickets_stake numeric,
group_id integer);
insert into report
values
('2020-07-20',12,569.6, 2, 44,1),
('2020-07-20',61,2000, 5, 260,2),
('2020-07-21',35,1244.2, 11, 250,1),
('2020-07-21',100,2500.5, 29, 575,2),
('2020-07-22',66,2511.8, 23, 670,1),
('2020-07-22',125,3358.2, 50, 990,2);
CREATE OR REPLACE FUNCTION report(arguments json)
RETURNS json AS
$BODY$
DECLARE
dateFrom date;
dateTo date;
selectedType integer;
BEGIN
dateFrom := cast(arguments->>'dateFrom' as date);
dateTo := cast(arguments->>'dateTo' as date);
selectedType := cast(arguments->>'selectedType' as integer);
RETURN (
WITH full_data as (
with tickets as (
select
report_day
, sum(tickets_no) as tickets_no
, sum(tickets_stake) as tickets_stake
FROM report
WHERE selectedType = 0
AND report_day between dateFrom and dateTo
GROUP BY 1)
, promo_tickets as (
select
report_day
, sum(promo_tickets_no) as promo_tickets_no
, sum(promo_tickets_stake) as promo_tickets_stake
FROM report
WHERE selectedType = 1
AND report_day between dateFrom and dateTo
GROUP BY 1)
select
t.report_day
, sum(coalesce(t.tickets_no,0) + coalesce(pt.promo_tickets_no,0)) as tickets_no
, sum(coalesce(t.tickets_stake,0) + coalesce(pt.promo_tickets_stake,0)) as tickets_no
FROM tickets t
LEFT JOIN promo_tickets pt on t.report_day = pt.report_day
GROUP BY 1
ORDER BY 1)
select row_to_json(full_data) from full_data
);
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
select * from report(json_build_object('dateFrom', '2020-07-20', 'dateTo', '2020-07-22','selectedType', 0 ))
因为您正试图从一个函数中 return 多行,而本应只 return 编辑一行。向您的函数添加一个参数,最好是一个主键列(我想 tickets_no
),例如
CREATE OR REPLACE FUNCTION report(arguments json, i_tickets_no int)
并将查询重写为
WITH full_data AS
(WITH tickets AS
(SELECT report_day,
SUM(tickets_no) AS tickets_no,
SUM(tickets_stake) AS tickets_stake
FROM report
WHERE selectedType = 0
AND report_day BETWEEN dateFrom AND dateTo
AND tickets_no = i_tickets_no
GROUP BY 1),
promo_tickets as
(select report_day,
SUM(promo_tickets_no) as promo_tickets_no,
SUM(promo_tickets_stake) as promo_tickets_stake
FROM report
WHERE selectedType = 1
AND report_day BETWEEN dateFrom AND dateTo
GROUP BY 1)
select t.report_day,
SUM(COALESCE(t.tickets_no, 0) + COALESCE(pt.promo_tickets_no, 0)) AS tickets_no,
SUM(COALESCE(t.tickets_stake, 0) +
COALESCE(pt.promo_tickets_stake, 0)) AS tickets_no
FROM tickets t
LEFT JOIN promo_tickets pt
ON t.report_day = pt.report_day
GROUP BY 1
ORDER BY 1)
并通过添加第二个参数来调用。
如果您希望您的函数像您的查询一样return 报告对象数组,请更改此部分:
select row_to_json(full_data) from full_data
要将行聚合到一个数组中:
select json_agg(row_to_json(full_data)) from full_data
如果你想让函数return多行,那么你需要做两个改变:
CREATE OR REPLACE FUNCTION report(arguments json)
RETURNS table (row_to_json json) AS
对于return
:
RETURN QUERY (
WITH full_data as (
已更新fiddle here.