是的,这可能是另一个greatest-n-per-group问题......但是我已经尝试了至少十几个已经在这里发布的问题的答案,找不到一个适用于我正在努力的问题做。这可能是我想要忽视的东西,或者我想要的只是略有不同。可能是第一个:/
我有两个表(InnoDB),一个用于图像集,每组一行,其中包含一些信息,如set_title,链接到的产品,开/关状态和dateadded:
图库集
每个图像的表格,每个图像都有一个或多个图像。虽然没有路径字段,我只是使用它有点像set_id / pic_id.jpg ...还有一些其他字段,如viewcounts等,但这些问题不需要,所以我把它们留了出来。
GalleryPics
基本上我想为最新的4套显示2张图片。我在下面有这个查询接近我想要的,它唯一不做的就是将它限制为每组2个:
SELECT s.`set_id`, s.`set_title`, s.`set_dateadded`, p.`pic_id`, p.`pic_dateadded`
FROM `GallerySets` s
LEFT JOIN `GalleryPics` p
ON (s.`set_id` = p.`set_id`)
WHERE s.set_status = 'online'
ORDER BY s.`set_dateadded` DESC, p.`pic_dateadded` ASC
它只是显示了一切。在其他问题(如this one)中,我看到改变在线并添加HAVING应该可以做到这一点:
ON (s.`set_id` = p.`set_id` AND s.`set_dateadded` < p.`pic_dateadded`)
HAVING COUNT(*) < 3
我已经尝试了各种各样的变种与HAVING,但它并没有让我更接近。它实际上返回零结果或每组一行,只要我添加任何类型的HAVING行。也许我正在尝试使用错误的最大n组解决方案?也许是因为我想对datetime字段进行排序而不是自动递增ID?
通缉结果
实际上想要更像是最近五集的前三张照片,但是为了给出一个不太长的结果例子......稍微调整一下。
set_id | set_title | set_dateadded | pic_id | pic_dateadded
4 | blah4 | 2011-10-04 00:00:00 | 32 | 2011-10-04 12:44:01
4 | blah4 | 2011-10-04 00:00:00 | 33 | 2011-10-04 12:44:02
3 | blah3 | 2011-10-03 00:00:00 | 26 | 2011-10-03 12:33:01
3 | blah3 | 2011-10-03 00:00:00 | 27 | 2011-10-03 12:33:02
2 | blah2 | 2011-10-02 00:00:00 | 11 | 2011-10-02 12:22:01
2 | blah2 | 2011-10-02 00:00:00 | 12 | 2011-10-02 12:22:02
1 | blah1 | 2011-10-01 00:00:00 | 1 | 2011-10-01 12:11:01
1 | blah1 | 2011-10-01 00:00:00 | 2 | 2011-10-01 12:11:02
开始认为让一个查询获得最新集合然后在php中使用while循环获取最新集合可能不是最糟糕的想法,以获得每个集合的几个图片。 :/
感谢George Psarakis的工作解决方案。这显示了最近四组中的前两张照片:
SET @rownum=0;
SET @last_group_id=0;
SELECT gp.pic_id, gp.pic_dateadded, gs.*,
@rownum:=IF(gp.set_id<>@last_group_id,1,@rownum+1) AS rn, @last_group_id:=gp.set_id
FROM GalleryPics gp JOIN
(
SELECT * FROM GallerySets WHERE set_status='online'
ORDER BY gs.set_dateadded DESC LIMIT 5
) AS gs
ON gs.set_id = gp.set_id
HAVING rn < 4
ORDER BY gs.set_dateadded DESC, gp.pic_dateadded ASC
(对于900多套和10000多张照片,查询时间约为0.0030秒)
答案 0 :(得分:0)
我不太确定,但你可以试试以下吗?
SET @rownum=0;
SET @last_group_id=0;
SELECT * FROM (
SELECT gp.*,gs.*,@rownum:=IF(gp.set_id<>@last_group_id,1,@rownum+1) AS rn,
@last_group_id:=gp.set_id FROM GalleryPics gp JOIN
(
SELECT * FROM GallerySets WHERE set_status='online'
ORDER BY set_dateadded DESC LIMIT 4
) AS gs
ON gs.set_id = gp.set_id
GROUP BY gp.set_id
ORDER BY gp.set_id,gp.pic_dateadded
) tmp WHERE rn < 3