Postgresql Postgres非常硬的动态选择语句

Postgresql Postgres非常硬的动态选择语句,postgresql,Postgresql,有这样的表和数据 CREATE TABLE solicitations ( id SERIAL PRIMARY KEY, name text ); CREATE TABLE donations ( id SERIAL PRIMARY KEY, solicitation_id integer REFERENCES solicitations, -- can be null created_at timestamp without time zone NOT NULL DEFA

有这样的表和数据

CREATE TABLE solicitations
(
  id SERIAL PRIMARY KEY,
  name text
);

CREATE TABLE donations
(
  id SERIAL PRIMARY KEY,
  solicitation_id integer REFERENCES solicitations, -- can be null
  created_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'),
  amount bigint NOT NULL DEFAULT 0
);


INSERT INTO solicitations (name) VALUES 
  ('solicitation1'), ('solicitation2');

INSERT INTO donations (created_at, solicitation_id, amount) VALUES 
  ('2018-06-26', null, 10), ('2018-06-26', 1, 20), ('2018-06-26', 2, 30),
  ('2018-06-27', null, 10), ('2018-06-27', 1, 20),
  ('2018-06-28', null, 10), ('2018-06-28', 1, 20), ('2018-06-28', 2, 30);
created_at  no_solicitation  1    2
____________________________________
2018-06-26  10               20   30
2018-06-27  10               20   0
2018-06-28  10               20   30
如何在下面的select语句中仅使用postgres使请求id动态

SELECT
"created_at"
-- make dynamic this begins
, COALESCE("no_solicitation", 0) AS "no_solicitation"
, COALESCE("1", 0) AS "1"
, COALESCE("2", 0) AS "2"
-- make dynamic this ends
FROM crosstab(
  $source_sql$
    SELECT
      created_at::date as row_id
    , COALESCE(solicitation_id::text, 'no_solicitation') as category
    , SUM(amount) as value
    FROM donations
    GROUP BY row_id, category
    ORDER BY row_id, category
  $source_sql$
, $category_sql$
  -- parametrize with ids from here begins
  SELECT unnest('{no_solicitation}'::text[] || ARRAY(SELECT DISTINCT id::text FROM solicitations ORDER BY id))
  -- parametrize with ids from here ends
  $category_sql$
) AS ct (
  "created_at" date
-- make dynamic this begins
, "no_solicitation" bigint
, "1" bigint
, "2" bigint
-- make dynamic this ends
)
select应该返回如下数据

CREATE TABLE solicitations
(
  id SERIAL PRIMARY KEY,
  name text
);

CREATE TABLE donations
(
  id SERIAL PRIMARY KEY,
  solicitation_id integer REFERENCES solicitations, -- can be null
  created_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'),
  amount bigint NOT NULL DEFAULT 0
);


INSERT INTO solicitations (name) VALUES 
  ('solicitation1'), ('solicitation2');

INSERT INTO donations (created_at, solicitation_id, amount) VALUES 
  ('2018-06-26', null, 10), ('2018-06-26', 1, 20), ('2018-06-26', 2, 30),
  ('2018-06-27', null, 10), ('2018-06-27', 1, 20),
  ('2018-06-28', null, 10), ('2018-06-28', 1, 20), ('2018-06-28', 2, 30);
created_at  no_solicitation  1    2
____________________________________
2018-06-26  10               20   30
2018-06-27  10               20   0
2018-06-28  10               20   30
应参数化select的请求ID与中的相同

    SELECT unnest('{no_solicitation}'::text[] || ARRAY(SELECT DISTINCT id::text FROM solicitations ORDER BY id))

你可以修改代码

我决定使用json,它比交叉表简单得多

WITH
  all_solicitation_ids AS (
    SELECT
      unnest('{no_solicitation}'::text[] ||
      ARRAY(SELECT DISTINCT id::text FROM solicitations ORDER BY id))
    AS col
  )
, all_days AS (
  SELECT
    -- TODO: compute days ad hoc, from min created_at day of donations to max created_at day of donations
    generate_series('2018-06-26', '2018-06-28', '1 day'::interval)::date
  AS col
)
, all_days_and_all_solicitation_ids AS (
  SELECT
    all_days.col AS created_at
  , all_solicitation_ids.col AS solicitation_id
  FROM all_days, all_solicitation_ids
  ORDER BY all_days.col, all_solicitation_ids.col
)
, donations_ AS (
  SELECT
    created_at::date as created_at
  , COALESCE(solicitation_id::text, 'no_solicitation') as solicitation_id
  , SUM(amount) as amount
  FROM donations
  GROUP BY created_at, solicitation_id
  ORDER BY created_at, solicitation_id
)
, donations__ AS (
  SELECT
    all_days_and_all_solicitation_ids.created_at
  , all_days_and_all_solicitation_ids.solicitation_id
  , COALESCE(donations_.amount, 0) AS amount
  FROM all_days_and_all_solicitation_ids
  LEFT JOIN donations_
    ON all_days_and_all_solicitation_ids.created_at = donations_.created_at
   AND all_days_and_all_solicitation_ids.solicitation_id = donations_.solicitation_id
)

SELECT
  jsonb_object_agg(solicitation_id, amount) ||
  jsonb_object_agg('date', created_at)
  AS data
FROM donations__
GROUP BY created_at
结果是什么

data
______________________________________________________________
{"1": 20, "2": 30, "date": "2018-06-28", "no_solicitation": 10}
{"1": 20, "2": 30, "date": "2018-06-26", "no_solicitation": 10}
{"1": 20, "2": 0, "date": "2018-06-27", "no_solicitation": 10}
我想这和我要求的不一样。 它只返回
data
列,而不是
date,no_requisition,1,2,…。
,为此,我需要使用
json_来记录
,但我不知道如何动态生成它的
作为
参数