Reputation: 13509
I have a table in MySQL -
ABC (User, Login_time, City)
and contains some data in it.
The result I want is Top 5 users form Noida should come at the top in the resultset and rest resultset should be sorted by login_time. See the fiddle here -
http://www.sqlfiddle.com/#!9/88c203/9
create table abc (user varchar(20), login_time date, city varchar(20));
insert into abc values ('A', curdate(), 'Noida'),
('B', '2017-04-16', 'Delhi'),
('C', '2017-04-14', 'Noida'),
('D', '2017-04-18', 'Kanpur'),
('E', '2017-04-13', 'Raebareli'),
('F', '2017-04-16', 'Sitapur'),
('G', '2017-04-17', 'Muradabad'),
('H', '2017-04-18', 'Noida'),
('I', '2017-04-13', 'Lucknow'),
('J', '2017-04-12', 'Noida');
The expected result is -
'A', 2017-04-19, 'Noida'
'C', '2017-04-14', 'Noida'
'H', '2017-04-18', 'Noida'
'D', '2017-04-18', 'Kanpur'
'G', '2017-04-17', 'Muradabad'
'B', '2017-04-16', 'Delhi'
'F', '2017-04-16', 'Sitapur'
'E', '2017-04-13', 'Raebareli'
'I', '2017-04-13', 'Lucknow'
'J', '2017-04-12', 'Noida'
And the query i tried is -
select * from (select user, login_time, city from abc
where city = 'Noida'
limit 3
union all
select user, login_time, city from abc
where user not in (select user, login_time, city from abc
where city = 'Noida'
limit 3)
limit 4, count)
order by login_time
When i try to execute the query in fiddle it throws error -
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
Any help would be greatly appreciated.
Upvotes: 1
Views: 80
Reputation: 1173
Try something like this:
select *, 1 as OrderHelp
from abc
where city = 'Noida'
limit 3
union all
select *, 2 as OrderHelp
from abc
where user not in (
select user
from abc
where city = 'Noida'
limit 3
)
order by OrderHelp, login_time desc
Upvotes: 0
Reputation: 49260
You can use parentheses to combine the separately ordered results.
(select user, login_time, city
from abc
where city = 'Noida'
--order by login_time desc > add this to sort by login_time
limit 5
)
union all
(select user, login_time, city
from abc
where city <> 'Noida'
order by login_time desc
limit 3
)
Because you have to include the non-top 5 rows from Noida in the result-set, you can use a left join
to get those and order by the login_time.
(select user, login_time, city
from abc
where city = 'Noida'
order by login_time desc
limit 3
)
union all
(select a1.user, a1.login_time, a1.city
from abc a1
left join (select user, login_time, city
from abc
where city = 'Noida'
order by login_time desc
limit 3) a2 --this derived table is the previous result-set of top n users from Noida
on a1.user=a2.user and a1.city= a2.city
where a2.user is null
order by a1.login_time desc
limit 7
)
Use a prepared statement to get the number of remaining rows other than the top 3 rows.
set @a= (select count(*) - 3 from abc);
prepare stmt from
'(select user, login_time, city
from abc
where city = ''Noida''
order by login_time desc
limit 3)
union all
(select a1.user, a1.login_time, a1.city
from abc a1
left join (select user, login_time, city
from abc
where city = ''Noida''
order by login_time desc
limit 3) a2
on a1.user=a2.user and a1.city= a2.city
where a2.user is null
order by a1.login_time desc
limit ?
)';
execute stmt using @a;
Upvotes: 1
Reputation: 16923
this will work if you are sure you'll have 3 record with city='noida'
select *
from
(
(
select user,login_timecity
from abc
where city='noida'
order by login_time
limit 3
)
union
(
select user,login_timecity
from abc
where x
order by city='noida' DESC, login_time
limit 3, x
)
) t
Upvotes: 0
Reputation: 1269513
If you want the users from Noida first, just use:
select abc.*
from abc
order by (city = 'Noida') desc,
login_time desc;
Upvotes: 0