Skip to content
Advertisement

How to pass a variable to a subselect in a view

I have a table of posts, post_likes, and I need a query that will give me both totals for likes for posts, and also a given specific user’s likes for those posts. This means I need a good way of giving MY_USER_ID as input data.

Here’s a query that works

create view post_view as 
select post.id,
       coalesce(sum(post_like.score),0) as score,
       (
         select score 
         from post_like 
         where post.id = post_like.post_id 
         and post_like.fedi_user_id = MY_USER_ID 
       ) as my_vote,
from post
  left join post_like on post.id = post_like.post_id
group by post.id;

BUT my ORM (rust diesel) doesn’t allow me to set or query for that necessary MY_USER_ID field, since it’s a subquery.

I’d really love to be able to do something like:

select * 
from post_view 
where my_user_id = 'X';

Advertisement

Answer

Expose my_user_id on select clause of view

-- get all of the user's score on all post, regardless of the user liking the post or not

create view post_view as

select 
    u.id as my_user_id,         
    p.id as post_id, 
    sum(pl.score) over (partition by p.id) as score,
    coalesce(pl.score, 0) as my_vote -- each u.id's vote
from user u
cross join post p
left join post_like pl on u.id = pl.fedi_user_id and p.id = pl.post_id;


select * from post_view where my_user_id = 'X';

UPDATE

This can obtain post’s scores even when no user is given

create view post_view as

with all_post as
(
    select        
        p.id as post_id,
        sum(pl.score) as score
    from post p
    left join post_like pl on p.id = pl.post_id
    group by p.id
)

select
    u.id as my_user_id,
    ap.post_id,
    ap.score,
    coalesce(pl.score, 0) as my_vote
from user u
cross join all_post ap
left join post_like pl on u.id = pl.fedi_user_id and ap.post_id = pl.post_id

union all

select 
    '' as my_user_id, 
    ap.post_id, 
    ap.score, 
    0 as my_vote
from all_post ap
;


select * from post_view where my_user_id = 'X';

When no user is passed, select the query denoted by my_user_id of ''

select * from post_view where my_user_id = '';
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement