You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Knex中按数组原始顺序对查询结果排序?

在Knex中按查询数组的原始顺序对SQLite结果排序

问题场景

我使用Knex执行查询时,通过whereIn指定了一个顺序至关重要的数组:

knex("users").select("id", "name").whereIn("song_num", [4, 1, 34])

但返回结果的顺序是1、4、34,和数组的原始顺序4、1、34不符。我了解MySQL可以用FIELD函数、PostgreSQL可以用ORDINALITY实现按数组原始顺序排序,但我使用的是SQLite,尝试用orderByRaw时程序直接崩溃,想知道Knex中有没有适配SQLite的解决方法?

解决方案:基于SQLite CASE语句的Knex实现

SQLite没有内置类似FIELD的排序函数,但可以通过CASE语句为数组中的每个元素分配对应的排序权重,Knex中可以动态生成这个逻辑:

基础写法

const targetSongNums = [4, 1, 34];
// 生成CASE语句的WHEN分支
const orderCaseClauses = targetSongNums.map((num, index) => `WHEN song_num = ${num} THEN ${index}`).join(' ');

const sortedResult = await knex("users")
  .select("id", "name")
  .whereIn("song_num", targetSongNums)
  .orderByRaw(`CASE ${orderCaseClauses} END`);

安全防注入写法

如果数组中的值来自用户输入,建议用参数绑定避免SQL注入:

const targetSongNums = [4, 1, 34];
// 生成带参数占位符的WHEN分支
const orderCaseClauses = targetSongNums.map((_, index) => `WHEN song_num = ? THEN ${index}`).join(' ');
// 整理绑定参数:每个song_num对应一个占位符,按顺序传入
const bindParams = targetSongNums.flatMap((num, idx) => [num, idx]);

const sortedResult = await knex("users")
  .select("id", "name")
  .whereIn("song_num", targetSongNums)
  .orderByRaw(`CASE ${orderCaseClauses} END`, bindParams);

原理说明

这种方法通过CASE语句将数组中的每个元素映射到它在原始数组中的索引位置,排序时按照这个索引值升序排列,就能保证结果和原始数组的顺序完全一致。

内容的提问来源于stack exchange,提问作者wynnawinner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 11:15:10