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

如何将含行值比较的SQL查询转换为Sequelize(v6)查询?

问题

我有如下SQL查询:

SELECT *
FROM funds
WHERE (fund_id, created_at) > ($1, $2)
ORDER BY created_at DESC
LIMIT 5;

我正尝试将其转换为Sequelize(v6)中findAll(...)查询的过滤对象,目标是通过(fund_id, created_at)实现键集分页,数据库用的是SQLite,且已为(fund_id, created_at)创建索引。

目前我的实现如下:

{
  where: {
    [Op.and]: [
      { fundId: { [Op.gt]: prev_fund_id } },
      { createdAt: { [Op.gt]: prev_created_at } },
    ],
  },
  limit: 5,
  order: [["created_at", "DESC"]],
}

但生成的SQL和预期不符,日志输出的SQL是:

SELECT `fund_id`, `name`, `description`, `created_at`, `updated_at` FROM `funds` WHERE (`fund_id` > '04e5b202-e62e-417a-b9d8-8cd5b6a1cb8f' AND `created_at` > '2023-02-13 07:38:36.683 +00:00') ORDER BY `created_at` DESC LIMIT 5;

我知道行值比较和AND逻辑并不等价,但Sequelize似乎没有对应的Op运算符,请问该如何用Sequelize实现这个查询?


解决方案

方法1:用Sequelize.literal写入原生行值比较条件

这是最稳妥的实现方式,直接通过原生SQL片段来实现行值比较,还能避免SQL注入:

const { Op, literal } = require('sequelize');

const queryOptions = {
  where: literal('(fund_id, created_at) > (:prevFundId, :prevCreatedAt)'),
  replacements: {
    prevFundId: prev_fund_id,
    prevCreatedAt: prev_created_at
  },
  limit: 5,
  order: [["created_at", "DESC"]],
};

方法2:利用Sequelize的数组比较语法(需兼容验证)

Sequelize v6对部分数据库支持行值比较的简化写法,可以通过字段数组与值数组的比较实现:

const { Op } = require('sequelize');

const queryOptions = {
  where: {
    [['fundId', 'createdAt']]: { [Op.gt]: [prev_fund_id, prev_created_at] }
  },
  limit: 5,
  order: [["created_at", "DESC"]],
};

注:这种写法需要确认你的Sequelize版本和SQLite驱动是否兼容,若出现语法报错,优先使用第一种literal方案。

关键说明

你之前的AND逻辑确实和行值比较不等价:行值比较(a,b) > (x,y)的实际逻辑是(a > x) OR (a = x AND b > y),这才是键集分页需要的规则——要么fund_id更大,要么fund_id相同时created_at更大,这样才能正确获取下一页的连续数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:02:29