From c138528915aa27c385323b396b3ebc527e2e37b0 Mon Sep 17 00:00:00 2001 From: ndwarshuis Date: Sun, 30 May 2021 01:31:00 -0400 Subject: [PATCH] ENH break histogram function into more convenient chunks --- etc/org-sql/viz_setup.sql | 50 +++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/etc/org-sql/viz_setup.sql b/etc/org-sql/viz_setup.sql index 773dc42..9b1ff41 100644 --- a/etc/org-sql/viz_setup.sql +++ b/etc/org-sql/viz_setup.sql @@ -4,36 +4,62 @@ as $$ select ts::time at time zone 'US/Eastern'; $$ language SQL; -CREATE OR REPLACE FUNCTION histogram(tname text, cname text, width int) -RETURNS TABLE(bin_number int, bin_interval text, count bigint) +create or replace function get_bin_num(x numeric, width int) +returns int +as $$ + -- select (floor(x/width)*width)::int; + select floor(x/width)::int; +$$ language SQL; + +CREATE OR REPLACE FUNCTION bin_ranges(tname text, cname text, width int) +RETURNS TABLE(bin_number int, bin_interval text) AS $func$ BEGIN RETURN QUERY EXECUTE format(' with recursive no_bins_t as ( - select min(floor(a.%1$s/%2$s)*%2$s)::int as bin_number from %3$s a + select min(get_bin_num(%1$s,%2$s)) as bin_number from %3$s a union all select bin_number + 1 as bin_number from no_bins_t where - bin_number < (select max(floor(a.%1$s/%2$s)) + 1 from %3$s a) + bin_number < (select max(get_bin_num(%1$s,%2$s)) + 1 from %3$s a) ) select bin_number, - concat(bin_number*%2$s, ''-'', bin_number*%2$s + %2$s - 1) as bin_interval, - case when count is null then 0 else count end as count + concat(bin_number*%2$s, ''-'', bin_number*%2$s + %2$s - 1) as bin_interval from no_bins_t - left join - (select - floor(a.%1$s/%2$s)*%2$s as ab_floor, + order by no_bins_t.bin_number;', + cname, + width, + tname + ); +END +$func$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION histogram(tname text, cname text, width int) +RETURNS TABLE(bin_number int, bin_interval text, count bigint) +AS $func$ +BEGIN +RETURN QUERY EXECUTE format(' + with binned as ( + select + get_bin_num(%1$s,%2$s) as ab_floor, count(*) as count from %3$s a group by ab_floor - order by ab_floor) as binned - on no_bins_t.bin_number*%2$s=binned.ab_floor - order by no_bins_t.bin_number;', + order by ab_floor + ) + + select + bin_number, + bin_interval, + case when b.count is null then 0 else b.count end as count + from bin_ranges(''%3$s'',''%1$s'',%2$s) r + left join binned b on r.bin_number=b.ab_floor + order by r.bin_number;', cname, width, tname