我有一个数据库表,它有两个字段,日期和名称。
我想让我的查询先按最新日期提取前20个元素,然后让查询的其余部分按名称的字母顺序提取其他元素。
这样,排名前20的最新产品将首先显示,然后按名称订购其余产品。
这有点难看,但您可以在一个查询中完成:
SELECT name,
`date`
FROM ( SELECT @rank := @rank + 1 AS rank,
name,
`date`
FROM (SELECT @rank := 0) dummy
JOIN products
ORDER BY `date` DESC, name) dateranked
ORDER BY IF(rank <= 20, rank, 21), name;
最里面的查询dummy
初始化我们的@rank
变量。下一个派生表dateranked
按最近性对所有行进行排名(通过name
打破联系)。然后,最外层的查询简单地按照我们计算的rank
对行进行重新排序,将大于20的秩视为秩#21,然后按照name
。
UPDATE:这个查询版本更紧凑,将条件排序逻辑放在最外面的ORDER BY中,使用IF()而不是CASE/END。
恐怕这必须通过向表中添加一个特殊列或创建一个临时表TPup来完成。如果你让我知道你是否对这些选择感兴趣,我会告诉你更多。
像下面这样的两个查询选项可能是可能的,但我的MySQL版本告诉我LIMIT在子查询中不可用。
SELECT `date`, `name` from `table` ORDER BY `date` LIMIT 0, 20;
SELECT `date`, `name` from `table` WHERE `id` NOT IN (SELECT `id` from `table` ORDER BY `date` LIMIT 0, 20) ORDER BY `name`;
使用sql UNION运算符组合两个SELECT查询的结果。
根据MySQL文档:
对单个SELECT语句使用ORDER BY并不意味着什么关于行在最终结果中出现的顺序,因为UNION默认情况下生成一组无序的行。
使用ORDER BY或LIMIT子句对整个UNION进行排序或限制结果,将各个SELECT语句用括号括起来,并将ORDER BY或LIMIT在最后一个后面。以下示例同时使用这两个子句:
(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;
编辑:我错过了解释OP需要按日期对一组结果进行排序,另一组结果按字母顺序进行排序的部分。我认为您需要创建一个临时字段来进行排序。SQL查询将类似于此。
(SELECT *, 'firstset' as set_id FROM t1 ORDER BY date LIMIT 0, 20)
UNION
(SELECT *, 'secondset' as set_id FROM t1 ORDER BY date LIMIT 20, 18446744073709551615)
ORDER BY
CASE
WHEN set_id='firstset' THEN date
WHEN set_id='secondset' THEN name
END DESC ;