简体   繁体   中英

Having trouble get the right output from a MySQL Query

I have a database that includes the following tables:

  • User
  • Category
  • Article

Inside our website we have a section called "editors pick" that has 5 of the best articles chosen by editors on that area.

Editors must set "is_recommended = yes" and also "recommended_location" which can be either 1,2,3,4, or 5; accordingly they will be placed on one of those 1-5 placements on the website.

Articles also have a "start_date" meaning the author can write an article assign it as is_recommended = yes and recommended_location = 3 and then set it for tomorrow 9pm. Therefore the article will only appear tomorrow and when it does it should sit on the 3 box of the editors pick.

Sometimes we may have an article such as below:

  • ID: 123
  • is_recommended: yes
  • recommended_location = 3
  • start_date = 06-05-2016 09:00:00 (let's say this is yesterday)

Which is currently holding the #3 spot.

I have another article:

  • ID: 456
  • is_recommended: yes
  • recommended_location = 3
  • start_date = 07-05-2016 09:00:00 (this is today and today it is already 11am)

However my query still continues to show ID: 123; while I want it to show the one in slot #3 that is the newest (meaning 456)

Can someone tell me what I am doing wrong in my query below, how can I assure that for each slot the newest item is selected?

This is the query:

select * 
from (
    select article.*, user.username, category.title as ctitle, user.firstname, user.lastname, category.slug as cslug, category.category_id as pid 
    from article 
    left join user on article.created_by = user.id 
    left join category on category.id = article.category_id 
    where article.status='active' 
    AND is_recommended='yes' 
    AND article.start_date<='".date('Y-m-d H:i:s')."' 
    AND recommended_location in (1,2,3,4,5) 
    order by start_date desc
 ) as x 
 group by recommended_location 
 limit 5

You havent't aggregation function so you don't need group by (eventually use distinct if this is what you need)

select * 
from (    select article.*, user.username, category.title as ctitle, user.firstname, user.lastname, category.slug as cslug, category.category_id as pid 
    from article 
    left join user on article.created_by = user.id 
    left join category on category.id = article.category_id 
    where article.status='active' 
    AND is_recommended='yes' 
    AND article.start_date<='".date('Y-m-d H:i:s')."' 
    AND recommended_location in (1,2,3,4,5) 
    order by start_date desc
 ) as x 
 limit 5

If you want only a article for each recommended_location you should use

(select article.*, user.username, category.title as ctitle, user.firstname, user.lastname, category.slug as cslug, category.category_id as pid 
from article 
left join user on article.created_by = user.id 
left join category on category.id = article.category_id 
where article.status='active' 
AND is_recommended='yes' 
AND article.start_date<='".date('Y-m-d H:i:s')."' 
AND recommended_location = '1' 
order by start_date desc limit 1)
union
(select article.*, user.username, category.title as ctitle, user.firstname, user.lastname, category.slug as cslug, category.category_id as pid 
from article 
left join user on article.created_by = user.id 
left join category on category.id = article.category_id 
where article.status='active' 
AND is_recommended='yes' 
AND article.start_date<='".date('Y-m-d H:i:s')."' 
AND recommended_location = '2' 
order by start_date desc limit 1)
union 
(select article.*, user.username, category.title as ctitle, user.firstname, user.lastname, category.slug as cslug, category.category_id as pid 
from article 
left join user on article.created_by = user.id 
left join category on category.id = article.category_id 
where article.status='active' 
AND is_recommended='yes' 
AND article.start_date<='".date('Y-m-d H:i:s')."' 
AND recommended_location = '3' 
order by start_date desc limit 1)   
union 
(select article.*, user.username, category.title as ctitle, user.firstname, user.lastname, category.slug as cslug, category.category_id as pid 
from article 
left join user on article.created_by = user.id 
left join category on category.id = article.category_id 
where article.status='active' 
AND is_recommended='yes' 
AND article.start_date<='".date('Y-m-d H:i:s')."' 
AND recommended_location = '4' 
order by start_date desc limit 1)  
union 
(select article.*, user.username, category.title as ctitle, user.firstname, user.lastname, category.slug as cslug, category.category_id as pid 
from article 
left join user on article.created_by = user.id 
left join category on category.id = article.category_id 
where article.status='active' 
AND is_recommended='yes' 
AND article.start_date<='".date('Y-m-d H:i:s')."' 
AND recommended_location = '5' 
order by start_date desc limit 1)  

Make the aggregation first and then join the data you need

select x.recommended_location, x.start_date, ... 
from
 ( select article.recommended_location, max(article.start_date) as  start_date 
    from article 
     where article.status='active' 
     AND is_recommended='yes' 
     AND article.start_date<='".date('Y-m-d H:i:s')."' 
    AND recommended_location in (1,2,3,4,5) 
    group by article.recommended_location
 ) as x 
inner join article on x.recommended_location = artice.recommended_location    
and x.start_date = article.start_date
inner join ...

But if 2 or more articles have the same start_date, you will get all of them this way...

Try this :

Use article.id with descending order in query

so your query is like this :

select * 
from (
    select article.*, user.username, category.title as ctitle, user.firstname, user.lastname, category.slug as cslug, category.category_id as pid 
    from article 
    left join user on article.created_by = user.id 
    left join category on category.id = article.category_id 
    where article.status='active' 
    AND is_recommended='yes' 
    AND article.start_date<='".date('Y-m-d H:i:s')."' 
    AND recommended_location in (1,2,3,4,5) 
    order by article.ID desc, recommended_location desc, start_date desc
 ) as x 
 group by recommended_location 
 limit 5

I hope you will get solution.

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