Skip to content

Instantly share code, notes, and snippets.

@davetapley
Created September 15, 2013 18:29
Show Gist options
  • Save davetapley/6573205 to your computer and use it in GitHub Desktop.
Save davetapley/6573205 to your computer and use it in GitHub Desktop.
Normalized histogram in psql
-- from: https://wiki.postgresql.org/wiki/Aggregate_Histogram
CREATE OR REPLACE FUNCTION hist_sfunc (state INTEGER[], val REAL, min REAL, max REAL, nbuckets INTEGER) RETURNS INTEGER[] AS $$
DECLARE
bucket INTEGER;
i INTEGER;
BEGIN
-- width_bucket uses nbuckets + 1 (!) and starts at 1.
bucket := width_bucket(val, min, max, nbuckets - 1) - 1;
-- Init the array with the correct number of 0's so the caller doesn't see NULLs
IF state[0] IS NULL THEN
FOR i IN SELECT * FROM generate_series(0, nbuckets - 1) LOOP
state[i] := 0;
END LOOP;
END IF;
state[bucket] = state[bucket] + 1;
RETURN state;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
-- Tell Postgres how to use the new function
DROP AGGREGATE IF EXISTS histogram (REAL, REAL, REAL, INTEGER);
CREATE AGGREGATE histogram (REAL, REAL, REAL, INTEGER) (
SFUNC = hist_sfunc,
STYPE = INTEGER[]
);
-- from: http://stackoverflow.com/a/8584506/21115
SELECT array_agg(ROUND(n, 2)) FROM unnest(ARRAY[1.53224,0.23411234]) AS n
-- from: http://www.postgresql.org/message-id/[email protected]
create or replace function sum_decimal_array( anyarray )
returns bigint
as $$
select sum($1[i])
from generate_series(
array_lower($1,1),
array_upper($1,1)
) g(i);
$$ language sql immutable;
CREATE FUNCTION
@davetapley
Copy link
Author

My goal is to get a normalized output from histogram, such that sum_decimal_array of the output would be 1.

I believe I have all the component here, but I can't get them to come together.

@davetapley
Copy link
Author

Trying to get my head around how this would work, I tried:

array_agg(unnest(histogram(...)))

But then I get:

ERROR:  aggregate function calls cannot be nested

Which makes me think I'm missing something here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment