Reputation: 91
i have the following table :
+------+------+-----+---------+------------+
| no | code |eot |group_id | compulsary |
+------+------+-----+---------+------------+
| 1005 | 101 | 51 | 1 | 1 |
| 1005 | 102 | 67 | 1 | 1 |
| 1005 | 121 | 65 | 1 | 1 |
| 1005 | 231 | 82 | 2 | 0 |
| 1005 | 232 | 56 | 2 | 0 |
| 1005 | 233 | 45 | 2 | 1 |
| 1005 | 313 | 80 | 3 | 0 |
| 1005 | 443 | 50 | 4 | 0 |
|------+------+-----+---------+------------+
now what i want is :
1.) return all records where group_id=1
,
2.) return the best two from group_id=2(however if compulsary=1
then include that row and the best from the remaining group_id=2
),
3.)return 1 row each from group_id=3
and group_id=4
and if compulsary=1
then return that row
the final result should have only seven rows:
+------+------+-----+---------+------------+
| no | code |eot |group_id | compulsary |
+------+------+-----+---------+------------+
| 1005 | 101 | 51 | 1 | 1 |
| 1005 | 102 | 67 | 1 | 1 |
| 1005 | 121 | 65 | 1 | 1 |
| 1005 | 231 | 82 | 2 | 0 |
| 1005 | 233 | 45 | 2 | 1 |
| 1005 | 313 | 80 | 3 | 0 |
| 1005 | 443 | 50 | 4 | 0 |
|------+------+-----+---------+------------+
with the compulsary=1
rows inluded like above;
so far I have this query though I don't know how to check for the compulsary
to get what I want:
select rg.*
from
(
select *
from
(
select
rgrade.*,
@rn := if(@gr=group_id,if(@gr:=group_id,@rn+1,@rn+1),if(@gr:=group_id,1,1)) as rn
from rgrade
cross join (select @rn:=0,@gr:=0) as vars
where admission_no=1005
) v
where (group_id=1)
or (group_id=2 and if(compulsary=1,rn<=1,rn<=2))
or (group_id in (3,4) and rn=1)
) rg
order by group_id;
the query returns the seven rows as expected but does not check for compulsary
in group_id=2
.
Any help much appreciated
Upvotes: 1
Views: 143
Reputation: 94859
You are trying to mimic standard SQL's
row_number() over (partition by group_id
order by case when compulsary = 1 then 1 else 0 end desc, eot desc)
with MySQL means. And I see the partitioning by group_id
in your query, but I don't see any ORDER BY to get the best records first.
Here is my attempt on it. There may be mistakes; I'm no MySQL guy.
select
no, code, eot, group_id, compulsary
from
(
select
no,
code,
eot,
compulsary,
@row_number :=
case when group_id = @last_group_id then @row_number + 1 else 1 end as row_number,
@last_group_id := group_id as group_id
from rgrade
cross join
(
select
@row_number := 0,
@last_group_id := -1
) as vars
where admission_no = 1005
order by group_id, (compulsary = 1) desc, eot desc
) ranked
where (group_id = 1)
or (group_id = 2 and row_number <= 2)
or (group_id = 3 and row_number = 1)
or (group_id = 4 and row_number = 1)
order by group_id, code;
Upvotes: 1
Reputation: 94859
You are describing several queries here, the result of which you want combined: All group_id = 1
, the two best group_id = 2
, the best of group_id = 3
, and the best of group_id = 4
. So write these queries and combine them with UNION ALL
. With "best" defined as compulsary = 1
preferred, then highest eot, you get:
(select * from mytable where group_id = 1)
union all
(select * from mytable where group_id = 2 order by compulsary = 1 desc, eot desc limit 2)
union all
(select * from mytable where group_id = 3 order by compulsary = 1 desc, eot desc limit 1)
union all
(select * from mytable where group_id = 4 order by compulsary = 1 desc, eot desc limit 1)
order by group_id, no, code
;
Upvotes: 2