sql—子查询返回的多行用作表达式,但仅在函数中使用

bxfogqkk  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(314)

当我使用一个函数时,它会给出上面提到的错误,但当同一个代码单独使用时,它工作得很好。问题出在哪里?
摆弄功能:https://dbfiddle.uk/?rdbms=postgres_12&fiddle=c4b0c8a59d2bd851284ed624ab1c335d
摆弄干净选择:https://dbfiddle.uk/?rdbms=postgres_12&fiddle=7ccca6c70061aff1f6c394815aa8e9b1
样本数据:

  1. create table report
  2. (report_day date,
  3. tickets_no integer,
  4. tickets_stake numeric,
  5. promo_tickets_no integer,
  6. promo_tickets_stake numeric,
  7. group_id integer);
  8. insert into report
  9. values
  10. ('2020-07-20',12,569.6, 2, 44,1),
  11. ('2020-07-20',61,2000, 5, 260,2),
  12. ('2020-07-21',35,1244.2, 11, 250,1),
  13. ('2020-07-21',100,2500.5, 29, 575,2),
  14. ('2020-07-22',66,2511.8, 23, 670,1),
  15. ('2020-07-22',125,3358.2, 50, 990,2);
  16. CREATE OR REPLACE FUNCTION report(arguments json)
  17. RETURNS json AS
  18. $BODY$
  19. DECLARE
  20. dateFrom date;
  21. dateTo date;
  22. selectedType integer;
  23. BEGIN
  24. dateFrom := cast(arguments->>'dateFrom' as date);
  25. dateTo := cast(arguments->>'dateTo' as date);
  26. selectedType := cast(arguments->>'selectedType' as integer);
  27. RETURN (
  28. WITH full_data as (
  29. with tickets as (
  30. select
  31. report_day
  32. , sum(tickets_no) as tickets_no
  33. , sum(tickets_stake) as tickets_stake
  34. FROM report
  35. WHERE selectedType = 0
  36. AND report_day between dateFrom and dateTo
  37. GROUP BY 1)
  38. , promo_tickets as (
  39. select
  40. report_day
  41. , sum(promo_tickets_no) as promo_tickets_no
  42. , sum(promo_tickets_stake) as promo_tickets_stake
  43. FROM report
  44. WHERE selectedType = 1
  45. AND report_day between dateFrom and dateTo
  46. GROUP BY 1)
  47. select
  48. t.report_day
  49. , sum(coalesce(t.tickets_no,0) + coalesce(pt.promo_tickets_no,0)) as tickets_no
  50. , sum(coalesce(t.tickets_stake,0) + coalesce(pt.promo_tickets_stake,0)) as tickets_no
  51. FROM tickets t
  52. LEFT JOIN promo_tickets pt on t.report_day = pt.report_day
  53. GROUP BY 1
  54. ORDER BY 1)
  55. select row_to_json(full_data) from full_data
  56. );
  57. END;
  58. $BODY$
  59. LANGUAGE plpgsql VOLATILE
  60. COST 100;
  61. select * from report(json_build_object('dateFrom', '2020-07-20', 'dateTo', '2020-07-22','selectedType', 0 ))
20jt8wwn

20jt8wwn1#

如果希望函数像查询一样返回报表对象数组,请更改此部分:

  1. select row_to_json(full_data) from full_data

要将行聚合到数组中,请执行以下操作:

  1. select json_agg(row_to_json(full_data)) from full_data

如果希望函数返回多行,则需要进行两个更改:

  1. CREATE OR REPLACE FUNCTION report(arguments json)
  2. RETURNS table (row_to_json json) AS

而对于 return :

  1. RETURN QUERY (
  2. WITH full_data as (

这里是最新的小提琴。

展开查看全部
pzfprimi

pzfprimi2#

因为您试图从只应返回一行的函数中返回多行。在函数中再添加一个参数,最好是一个主键列(我想 tickets_no )例如

  1. CREATE OR REPLACE FUNCTION report(arguments json, i_tickets_no int)

并将查询重写为

  1. WITH full_data AS
  2. (WITH tickets AS
  3. (SELECT report_day,
  4. SUM(tickets_no) AS tickets_no,
  5. SUM(tickets_stake) AS tickets_stake
  6. FROM report
  7. WHERE selectedType = 0
  8. AND report_day BETWEEN dateFrom AND dateTo
  9. AND tickets_no = i_tickets_no
  10. GROUP BY 1),
  11. promo_tickets as
  12. (select report_day,
  13. SUM(promo_tickets_no) as promo_tickets_no,
  14. SUM(promo_tickets_stake) as promo_tickets_stake
  15. FROM report
  16. WHERE selectedType = 1
  17. AND report_day BETWEEN dateFrom AND dateTo
  18. GROUP BY 1)
  19. select t.report_day,
  20. SUM(COALESCE(t.tickets_no, 0) + COALESCE(pt.promo_tickets_no, 0)) AS tickets_no,
  21. SUM(COALESCE(t.tickets_stake, 0) +
  22. COALESCE(pt.promo_tickets_stake, 0)) AS tickets_no
  23. FROM tickets t
  24. LEFT JOIN promo_tickets pt
  25. ON t.report_day = pt.report_day
  26. GROUP BY 1
  27. ORDER BY 1)

并通过添加第二个参数来调用。
演示

展开查看全部

相关问题