Question

I have a small Facebook card game where users can rate each other.

Those ratings are stored in a PostgreSQL 8.4.13 table pref_rep as a boolean value nice, which can be null too:

# \d pref_rep;
                                       Table "public.pref_rep"
  Column   |            Type             |                         Modifiers
-----------+-----------------------------+-----------------------------------------------------------
 id        | character varying(32)       | not null
 author    | character varying(32)       | not null
 nice      | boolean                     |
 comment   | character varying(256)      |
 rep_id    | integer                     | not null default nextval('pref_rep_rep_id_seq'::regclass)
Indexes:
    "pref_rep_pkey" PRIMARY KEY, btree (id, author)
Check constraints:
    "pref_rep_check" CHECK (id::text <> author::text)
Foreign-key constraints:
    "pref_rep_author_fkey" FOREIGN KEY (author) REFERENCES pref_users(id) ON DELETE CASCADE
    "pref_rep_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) ON DELETE CASCADE

I would like to make those ratings visible as a pie chart on user avatars:

enter image description here

So I am trying the following -

First select a quotient (nice / nice + not nice) from pref_rep:

# select id,
    (count(nullif(nice, false)) - count(nullif(nice, true))) / count(nice) as rating
    from pref_rep
    where nice is not null
    group by id;

           id            | rating
-------------------------+--------
 DE10072                 |     -1
 DE10086                 |      0
 DE10087                 |      1
 DE10088                 |     -1
 DE10095                 |      0
 DE10097                 |      1
 DE10105                 |      0

Why doesn't it print a 0-to-1 floating number here?

And then I am trying to store that quotient in the pref_users table - because of performance reasons I want to do it by a nightly cronjob:

# update pref_users u
set rating = s.rating
from (
        select
        id,
        count(nullif(nice, false)) - count(nullif(nice, true)) / count(nice) as rating
        from pref_rep
        where nice is not null
        group by id
) s
where u.id = s.id;

UPDATE 25419

This completes quickly, but why are all rating values in pref_users are set to null?

Was it helpful?

Solution

The rating:

select id,
    coalesce(
        (count(nice or null) - count(not nice or null))::float
        / count(nice)
    , 0) as rating
from pref_rep
group by id;

count does not count nulls. true or null will return true. false or null will return null. It is all casted to float to make a float return.

As to why your update only yields nulls I don't know. Post some sample data so we can play with it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top