2016-06-08 81 views
1

正确的输出我有包括以下表的数据库:有麻烦了从MySQL查询

  • 用户
  • 类别
  • 文章

里面我们的网站,我们有一个部分称为“编辑选择”,其中有5篇编辑在该领域选择的最佳文章。

编辑必须设置“is_recommended = yes”和“recommended_location”,它可以是1,2,3,4或5;因此他们将被放置在网站上的1-5个展示位置之一。

文章还有一个“start_date”,意思是作者可以写一篇文章,将其指定为is_recommended = yes和recommended_location = 3,然后将其设置为明天晚上9点。因此这篇文章只会在明天出现,当它出现时,它应该坐在编辑选择的3盒中。

有时,我们可以具有制品如以下:

  • ID:123
  • is_recommended:是
  • recommended_location = 3
  • 起始日期= 2016年6月5日九时00分00秒(假设这是昨天)

其中目前排名第3。

我有另一篇文章:

  • ID:456
  • is_recommended:是
  • recommended_location = 3
  • 起始日期= 2016年7月5日九点00分00秒(这是今天和今天已经是上午11点)

但是我的查询仍然显示ID:123;而我希望它显示插槽#3是最新的(含义456)

有人可以告诉我我做错了什么在我的查询下面,我怎么能保证每个插槽最新的项目是选择?

这是查询:

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 
+0

即使手动将1天添加到start_date,也应该有end_date比较。这样你可以使用像BETWEEN start_date和end_date之类的东西...所以在应该返回的行之间没有混淆。 –

+0

@Turo提供您想要的解决方案。这是你试图解决的一个不平凡的问题。阅读[这篇文章](http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/)关于试图解决这个问题问题类型 – AgRizzo

+0

谢谢@AgRizzo这正是问题所在。现在把2 + 2放在一起。 – Hossj

回答

2

您havent't聚集功能,所以你如果只希望每个recommended_location一个文章,你应该使用

不需要按组(最终使用不同的,如果这是你所需要的)

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 

(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) 
+0

谢谢。不幸的是,这不会产生正确的结果。 我需要获取每个recommended_location的最新项目;然而,这个查询是让他们随机放置它们;我现在有两个项目在1-5被设置为recommended_location = 3 – Hossj

+0

我已经更新了答案 – scaisEdge

+0

我还没有检查这是否工作,但这不会是一个巨大的负载在服务器上?我们网站上有超过10万用户,我正试图寻找优化方法。我知道我们可以缓存,但通常这个查询至少可以说是很可怕的。 – Hossj

0

试试这个:以降序排列查询

使用article.id

所以你的查询是这样的:

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 

我希望你能得到解决方案。

+0

感谢你的这一点,不幸的是,它并没有给我我期待的结果。 – Hossj

1

先进行聚合,然后加入数据,需要

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 ... 

但我f 2或更多文章具有相同的start_date,您将以这种方式获得所有文件...