简体   繁体   中英

Generating JSON response with PostgreSQL for Rails

I'm currently executing a SQL statement in Rails and while it works I've come to realize I need a different format and am attempting to accomplish this in PostreSQL. This is my query:

    sql = "SELECT one_month_high - one_month_low as one_month,
          three_month_high - three_month_low as three_month,
          six_month_high - six_month_low as six_month,
          twelve_month_high - twelve_month_low as twelve_month,
          ytd_high - ytd_low as ytd,
          saved_on
          FROM daily_high_lows
          ORDER BY saved_on DESC;"

Which returns:

#<PG::Result:0x007fdb4aea1fa0 status=PGRES_TUPLES_OK ntuples=380 nfields=6 cmd_tuples=380>
...
{"one_month"=>"544", "three_month"=>"214", "six_month"=>"9","twelve_month"=>"122",
"ytd"=>"143", "saved_on"=>"2016-06-09 00:00:00"}
{"one_month"=>"1283", "three_month"=>"475", "six_month"=>"22","twelve_month"=>"189",
"ytd"=>"517", "saved_on"=>"2016-06-08 00:00:00"}

I've come to realize that I require a format:

[
  {
    name: "One Month",
    data: {
      2016-06-09 00:00:00: 544,
      2016-06-08 00:00:00: 1283
    }
  },
  {
    name: "Three Month",
    data: {
     2016-06-09 00:00:00: 214,
     2016-06-08 00:00:00: 475
    }
  }, etc...
] 

I've been trying to research how to do this but it's a bit beyond me currently so I could use some direction.

You should be able to use the to_json method available in rails. So response.to_json should yield what you need.

I think if you have a lot of records, building the JSON inside Postgres is a great approach. Postgres didn't really get very useful JSON-building functions until 9.4 though, so I recommend you be at least there if not higher. Anyway, this seems to give you what you want:

WITH seqs AS (
  SELECT  json_object_agg(saved_on::text, one_month_high ORDER BY saved_on) one_month_highs,
          json_object_agg(saved_on::text, one_month_low ORDER BY saved_on) one_month_lows
  FROM    daily_high_lows
)
SELECT  json_agg(j)
FROM    (
  SELECT json_build_object('name', 'One Month Highs', 'data', one_month_highs)
  FROM   seqs
  UNION ALL
  SELECT json_build_object('name', 'One Month Lows', 'data', one_month_lows)
  FROM seqs
) x(j)
;

Tested like so:

t=# create table daily_high_lows (one_month_high integer, one_month_low integer, three_month_high integer, three_month_low integer, six_month_high integer, six_month_low integer, twleve_month_high integer, twelve_month_low integer, ytd_high integer, ytd_low integer, saved_on timestamp);
t=# insert into daily_high_lows (one_month_high, one_month_low, three_month_high, three_month_low, saved_on) values (1, 10, 3, 6, '2016-06-08');
t=# insert into daily_high_lows (one_month_high, one_month_low, three_month_high, three_month_low, saved_on) values (2, 9, 3, 8, '2016-03-09');
t=# with seqs as (select json_object_agg(saved_on::text, one_month_high order by saved_on) one_month_highs, json_object_agg(saved_on::text, one_month_low order by saved_on) one_month_lows from daily_high_lows) select json_agg(j) from (select json_build_object('name', 'One Month Highs', 'data', one_month_highs) from seqs union all select json_build_object('name', 'One Month Lows', 'data', one_month_lows) from seqs) x(j);
                                                                                              json_agg                                                                                              
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [{"name" : "One Month Highs", "data" : { "2016-03-09 00:00:00" : 2, "2016-06-08 00:00:00" : 1 }}, {"name" : "One Month Lows", "data" : { "2016-03-09 00:00:00" : 9, "2016-06-08 00:00:00" : 10 }}]
(1 row)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM