PostgreSQL – Execute Default Query When No Rows Returned

default valuepostgresql

I need to calculate the average score of a list of userId.

I have a table user_place_score:

(user_id, place_id, score)

Sometimes I do not have the score (no row for (user_id,place_id) in the table) so I need to fetch a "default" score from the table default_place_score:

(place_id, score)

Is is possible in PostgreSQL to do this in one query? For a given list of users and one place_id, select all their scores in the user_place_score and if no row is found then take the score found if the default_place_score table?

Basically I want to avoid doing this kind of stuff:

for (Integer userId : userIds) {
  score = (query to fetch the score for this userId)
  if (score == null)
    defaultScore = (query to fetch the default score for this PlaceId)

  total = total + defaultScore
}

//return the average
return total/numberOfUser

Best Answer

It seemed you need a simple LEFT JOIN but with the added comments, it gets a bit more complicated:

SELECT 
    u.user_id,
    p.place_id,
    COALECSE(ups.score, d.score) AS score
FROM 
    user AS u
  CROSS JOIN                                          -- the places we are
    (VALUES (1),(2),(3),...,(10)) AS p (place_id)     -- interested in
  LEFT JOIN
    user_place_score AS ups
      ON  ups.user_id = u.user_id
      AND ups.place_id = p.place_id
  LEFT JOIN 
    default_place_score AS d
      ON d.place_id = p.place_id
WHERE                                         -- the users we are
    u.user_id IN (6, 28, 496, ...) ;          -- interested in