简体   繁体   中英

combine two select queries from the same mysql table

We have a table of users with column membership_end which is, as the name say - the date when users membership end. Now some users never purchase membership so that field is empty. For some users, that field is in the past (membership expired). What I need is to sort the active members first (ordered by the membership_end date desc), then the rest of the users in some independent sorting order. Basically we need to show active members on top.

SELECT * FROM accounts where membership_end>=now() 
order by membership_end desc
union
???
  • Should we use union or something else?
  • What would be a second query to avoid duplicates?

Thanks in advance

Ok, to clear things up a bit.

SELECT * FROM accounts where membership_end>=now()
order by membership_end desc

gives us 12 active members and this is fine. we then have this:

SELECT * FROM accounts where membership_end<now()
order by id desc

we simply need to combine these two in one query. that's all.

EDIT: Actually i figured it out. It's quite simple.

SELECT id, membership_end FROM accounts ORDER BY membership_end >= NOW( ) DESC , id DESC

no unions. no complicated queries :-)

You can sort null values to be first, so you could avoid unions :

SELECT membership_end FROM accounts 
where membership_end>=now() or membership_end is null 
ORDER BY [membership_end] IS NULL DESC, [membership_end] DESC

If you do not want duplicates I would recommend to do this. I don't know what condition you want to use to filter members with null membership_end filed but if all I would do something like that:

SELECT membership_end FROM accounts where membership_end>=now() or membership_end is null order by membership_end desc

Descending ordering should put members with null membership_end in the end of list so you may want to add additional ordering.

Try something like this:

SELECT membership_end FROM table1 where membership_end>=now() 
Union all
SELECT membership_end FROM table2 where membership_end>=now() 

this will combine table1 and table2

The important bit is 1 field for table1 and 1 field for table2 only. It must be the same.

Two tricks here 1) associate ids with dates by creating a combined date + id field, historic and nulls have been given a seed date in the future to avoid overlaps with future dated members (you may wish to push this out) 2) allocate a srce number to the unioned statements.

/*
create table m (id int, enddte date);
truncate table m;
insert into m values
(1,null),(2,'2016-10-01'),(3,'2016-11-10'),(4,'2016-02-01'),(5,'2016-03-01'),(6,null);
*/
select * from
(
select  1 as srce,m.id,m.enddte ,
         year(m.enddte) * 10000 + month(m.enddte) * 100 + m.id as uniqueid
from        m
where       m.enddte >= now()

) s
union
(
select  2,id,enddte,
            year(cast('2050-01-01'  as date)) * 10000 + month(cast('2050-01-01'  as date)) * 100  + id
from        m
where       m.enddte < now() or m.enddte is null

) 

order       by srce,uniqueid desc

or you could do this without a union

select  * from
(
select  case 
            when enddte >= now() then 1
            else 2
            end as srce,
          id, enddte,
          case 
            when enddte >= now() then  year(m.enddte) * 10000 + month(m.enddte) * 100 + m.id 
            else    year(cast('2050-01-01'  as date)) * 10000 + month(cast('2050-01-01'  as date)) * 100  + id
            end as uniqueid
from        m
) s order       by srce,uniqueid desc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM