导航菜单

目前我在Typecho圈里看见的文章置顶实现都是使用两个 Select,第一个Select是查询置顶的文章,第二个Select是查询剩余的文章。

这样实现有BUG,而且也不优雅。
置顶x篇文章首页文章数就变成 pageSize + x 了。

法1

最简单就是新增一个排序字段了。这是MySQL的,SQLITE怎么写忘记了。

ALTER TABLE `prefix_contents` ADD `sticky` DEFAULT 0;

这样的缺点就是多一个没什么用字段,毕竟只有很少的文章需要置顶。而且修改sticky字段麻烦还需要写一个接口来实现。

查询的时候双字段排序就行。

select * from `prefix_contents` order by sticky desc, created desc

法2

把置顶字段信息存到 prefix_fields表。
使用any_value()来防止值不存在。
同样的双字段排序。

select *, any_value(`int_value`) as sticky from `prefix_contents` left outer join `prefix_fields` on `prefix_contents`.`cid` = `prefix_fields`.`cid` group by `prefix_contents`.`cid` order by sticky desc, created desc

法3(推荐)

把使用 case 来生成置顶字段
88,90就是想置顶的文章

select *, case when cid in (88, 90) then 100 else 0 end sticky from xmp_contents xc order by sticky desc,created desc;

已有 5 条评论

  1. jclser
    广东省

    结果还是要增加字段吗。。其实你说的那个BUG也是有解决方法的,$this->parameter->pageSize就是。

    1. Ryan
      未知地区

      直接设置$this->parameter->pageSize会丢文章,有多少置顶丢多少

  2. 流星
    浙江省

    这个方法确实优雅了,不过我想了下,这样应该会降低查询效率,程序得一个个去匹配所有文章,计算出“case when cid in (88, 90) then 100 else 0 end”的值,然后进行排序,用不上索引了。法1的话得给新字段加索引。法2排序用了两个表的字段,也得全表扫描。。

    1. Ryan
      未知地区

      其实本来就有 order 字段了,所以法1利用原来的 order 字段就行