Mysql:按子查询的最大N值排序
我准备用这个方法来解决问题。
前言:我想用任何N进行工作,但为了简单起见,我将N设置为3。
我有一个查询(特别是MySQL),它需要从表中获取数据,并根据该表的前3个值进行排序,并在该后退回到其他排序条件之后进行排序。
所以基本上我有这样的东西:
SELECT tbl.id
FROM
tbl1 AS maintable
LEFT JOIN
tbl2 AS othertable
ON
maintable.id = othertable.id
ORDER BY
othertable.timestamp DESC,
maintable.timestamp DESC
这是所有基本的教科书的东西。 但问题是,我需要第一个ORDER BY子句,只在其他时间戳中获得三个最大值,然后在maintainble.timestamp上回退。
另外,对其他参数进行LIMIT 3子查询并加入它是不行的,因为这需要使用适用于维护的任意数量的WHERE条件。
我几乎可以使用这种基于用户变量的方法进行工作,但由于它没有考虑到排序,所以它失败了,所以它会找到它找到的第一个三个其他值:
ORDER BY
(
IF(othertable.timestamp IS NULL, 0,
IF(
(@rank:=@rank+1) > 3, null, othertable.timestamp
)
)
) DESC
(在语句前加@rank:= 0)
所以...有关于此的任何提示? 这个问题我正在失去理智。 我的另一个参数是,因为我只是改变了一个现有的(非常复杂的)查询,我不能做一个包装外部查询。 另外,如上所述,我在MySQL上,所以任何使用ROW_NUMBER函数的解决方案都是不可及的。
感谢所有提前。
编辑。 以下是一些示例数据,其中的时间戳简化为更简单的整数以说明我需要的内容:
maintable
id timestamp
1 100
2 200
3 300
4 400
5 500
6 600
othertable
id timestamp
4 250
5 350
3 550
1 700
=>
1
3
5
6
4
2
如果出于任何原因,我们在查询中添加WHERE not maintainble.id = 5,这里是我们应该得到的:
1
3
4
6
2
...因为现在4是其中前3个值中的其中之一。
所以,正如你所看到的,来自othertable的id为4的行不包含在排序中,因为它是时间戳值降序中的第四个,因此它退回到由基本时间戳排序。
真实世界需要的是这样的:我拥有“可维护”的内容,“其他”基本上是特色内容的标记,具有“特色日期”的时间戳。 我有一个观点,我应该把最后3个特色项目放到最上面,剩下的列表只是一个倒序年表。
也许是这样的。
SELECT
id
FROM
(SELECT
tbl.id,
CASE WHEN othertable.timestamp IS NULL THEN
0
ELSE
@i := @i + 1
END AS num,
othertable.timestamp as othertimestamp,
maintable.timestamp as maintimestamp
FROM
tbl1 AS maintable
CROSS JOIN (select @i := 0) i
LEFT JOIN tbl2 AS othertable
ON maintable.id = othertable.id
ORDER BY
othertable.timestamp DESC) t
ORDER BY
CASE WHEN num > 0 AND num <= 3 THEN
othertimestamp
ELSE
maintimestamp
END DESC
修改答案:
select ilv.* from
(select sq.*, @i:=@i+1 rn from
(select @i := 0) i
CROSS JOIN
(select m.*, o.id o_id, o.timestamp o_t
from maintable m
left join othertable o
on m.id = o.id
where 1=1
order by o.timestamp desc) sq
) ilv
order by case when o_t is not null and rn <=3 then rn else 4 end,
timestamp desc
SQLFiddle在这里。
修改subquery sq
where 1=1
条件以匹配所需的复杂选择条件,并在最终order by
后添加适当的limit
条件order by
满足分页要求。
你可以使用如下的联合查询吗?
(SELECT id,timestamp,1 AS isFeatured FROM tbl2 ORDER BY timestamp DESC LIMIT 3)
UNION ALL
(SELECT id,timestamp,2 AS isFeatured FROM tbl1 WHERE NOT id in (SELECT id from tbl2 ORDER BY timestamp DESC LIMIT 3))
ORDER BY isFeatured,timestamp DESC
这可能有点多余,但它在语义上更接近你所问的问题。 这也可以让你参数化想要返回的特色结果的数量。
链接地址: http://www.djcxy.com/p/14899.html