Postgresql - Condition on where clause with join

大城市里の小女人 提交于 2019-12-25 08:08:48

问题


I am trying to add a join for a particular condition to my query:

select *
from (
    select
        row_number() over (partition by dl.value order by random()) as rn,
        dl.value,
        q.question_text, q.option_a, q.option_b, q.option_c, q.option_d,
        q.correct_answer, q.image_link, q.question_type
    from
        questions_bank q
        inner join
        sports_type st on st.id = q.sports_type_id
        inner join
        difficulty_level dl on dl.id = q.difficulty_level_id
    where st.game_type = lower('cricket') and dl.value in ('E','M','H')
) s
where 
    value = 'E' and rn <= 7 or
    value = 'M' and rn <= 4 or
    value = 'H' and rn = 1

So, if value = 'E', 50% of these questions (7) should be from a 'general' question category.

Something like "case when dl.value='E' then rn=4 (50% of 7) from question_category='general', 3 (7-4) else 7 end"

(I need to add a join like INNER JOIN question_category qc ON qc.id = q.question_category_id)

For other values (M/H), there shouldn't be any join with question_category

Refer question to see the original question.

UPDATE:

I am trying to do:

select *                                                          
   from (
          select
                row_number() over (partition by dl.value order by random()) as rn,
                row_number() over (partition by dl.value, LOWER(qc.value) = LOWER('general') order by random()) as rnc,
                dl.value, qc.value as question_category,
                q.question_text, q.option_a, q.option_b, q.option_c, q.option_d,
                q.correct_answer, q.image_link, q.question_type
            from
                questions_bank q
                inner join
                question_category qc on qc.id = q.question_category_id
                inner join
                sports_type st on st.id = q.sports_type_id
                inner join
                difficulty_level dl on dl.id = q.difficulty_level_id
            where st.game_type = lower('cricket') and dl.value in ('E','M','H')
        ) s
   where
        (value = 'E' and rnc <= 4) or (value = 'E' and rn <= 3)or
        value = 'M' and rn <= 3 or
        value = 'H' and rn <= 2;

but this is returning extra rows for value ='E'. (4 from rnc and 4 from rn when value='E'). What am I missing?


回答1:


SELECT *
FROM (
    SELECT
        row_number() over (partition by dl.value order by random()) as rn
        , dl.value
        , q.question_text, q.option_a, q.option_b, q.option_c, q.option_d
        , q.correct_answer, q.image_link, q.question_type
    FROM
        questions_bank q
        JOIN sports_type st ON st.id = q.sports_type_id
        JOIN difficulty_level dl ON dl.id = q.difficulty_level_id
    WHERE st.game_type = lower('cricket') AND dl.value IN ('E','M','H')
    AND ( dl.value = 'E'    -- No extra condition for 'E'
        OR EXISTS           -- Extra condition for non-'E'
          (SELECT * FROM question_category qc
          WHERE qc.id = q.question_category_id
          )
        )
) s
WHERE value = 'E' AND rn <= 7 
   or value = 'M' AND rn <= 4 
   or value = 'H' AND rn = 1
        ;



回答2:


I gave the general category the 1 id. Replace as necessary.

select *
from (
    select
        row_number() over (partition by dl.value order by random()) as rn,
        row_number() over (
            partition by dl.value, question_category_id = 1
            order by random()
        ) as rnc,
        dl.value,
        q.question_text, q.option_a, q.option_b, q.option_c, q.option_d,
        q.correct_answer, q.image_link, q.question_type
    from
        questions_bank q
        inner join
        sports_type st on st.id = q.sports_type_id
        inner join
        difficulty_level dl on dl.id = q.difficulty_level_id
        inner join
        question_category qc on qc.id = q.question_category_id
    where st.game_type = lower('cricket') and dl.value in ('E','M','H')
) s
where 
    value = 'E' and rn <= 4 or
    value = 'M' and rnc <= 4 or
    value = 'H' and rn = 1



回答3:


I could figure out the way,

following is what I came up with.

select *
                from (
                    select
                        row_number() over (partition by dl.value order by random()) as rn,
                        row_number() over (partition by dl.value, LOWER(qc.value) = LOWER('general') order by random()) as rnc,
                        row_number() over (partition by dl.value, LOWER(qc.value) != LOWER('general') order by random()) as rnq,
                        dl.value, qc.value as question_category,
                        q.question_text, q.option_a, q.option_b, q.option_c, q.option_d,
                        q.correct_answer, q.image_link, q.question_type
                    from
                        questions_bank q
                        inner join
                        question_category qc on qc.id = q.question_category_id
                        inner join
                        sports_type st on st.id = q.sports_type_id
                        inner join
                        difficulty_level dl on dl.id = q.difficulty_level_id
                    where st.game_type = lower('cricket') and dl.value in ('E','M','H')
                ) s
                where
                    (value = 'E' and rnq <= 4 and LOWER(question_category) != LOWER('general')) or
                    (value = 'E' and rnc <= 3 and LOWER(question_category) = LOWER('general')) or
                    value = 'M' and rn <= 3 or
                    value = 'H' and rn <= 2


来源:https://stackoverflow.com/questions/42160359/postgresql-condition-on-where-clause-with-join

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!