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

如何在Drizzle ORM的WHERE子句中使用子查询实现指定查询

用Drizzle ORM实现SQLite分组取最新记录

数据背景

表A的原始数据:

id  name    last_updated
1   Apple   100
2   Banana  100
3   Apple   200
4   Banana  200
5   Carrot  200
6   Banana  300
7   Apple   300

需求

获取每个name对应的last_updated小于等于指定参数(示例:250)的最新记录,预期结果:

idnamelast_updated
3Apple200
4Banana200
5Carrot200

数据库初始化SQL

-- INIT database
CREATE TABLE IF NOT EXISTS A (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    last_updated INTEGER NOT NULL
);
INSERT INTO A (name, last_updated) VALUES ('Apple', 100);
INSERT INTO A (name, last_updated) VALUES ('Banana', 100);
INSERT INTO A (name, last_updated) VALUES ('Apple', 200);
INSERT INTO A (name, last_updated) VALUES ('Banana', 200);
INSERT INTO A (name, last_updated) VALUES ('Carrot', 200);
INSERT INTO A (name, last_updated) VALUES ('Banana', 300);
INSERT INTO A (name, last_updated) VALUES ('Apple', 300);

原生SQL实现

-- QUERY database
SELECT a.id, a.name, a.last_updated
FROM A AS a
WHERE a.last_updated = (
    SELECT MAX(last_updated)
    FROM A
    WHERE name = a.name
    AND last_updated <= 250
)
AND a.last_updated <= 250;

错误的Drizzle尝试

const dayLuxonToBigint = 250

return await db
  .select()
  .from(A)
  .where(
    and(
      lte(a.last_updated, dayLuxonToBigint),
      sql`SELECT max(${A.last_updated}) FROM ${A}
WHERE id = a.id
AND ${A.last_updated} <= ${dayLuxonToBigint}`,
    ),
  );

正确的Drizzle ORM写法

写法一:直接对应原生SQL逻辑

这种写法完全匹配原生SQL的子查询逻辑,注意给内层表加别名避免字段歧义:

import { sql, eq, lte, and } from 'drizzle-orm';
import { db } from './your-db-connection'; // 替换为你的数据库连接
import { A as a } from './schema'; // 替换为你的schema定义

const dayLuxonToBigint = 250n; // *注意类型匹配,SQLite INTEGER对应BigInt*

const result = await db
  .select({
    id: a.id,
    name: a.name,
    last_updated: a.last_updated,
  })
  .from(a)
  .where(
    and(
      lte(a.last_updated, dayLuxonToBigint),
      eq(
        a.last_updated,
        sql`(SELECT max(${a.last_updated}) FROM ${a} AS inner_a WHERE inner_a.name = ${a.name} AND inner_a.last_updated <= ${dayLuxonToBigint})`
      )
    )
  );

写法二:类型安全的子查询构造器

使用Drizzle内置的子查询API,更符合ORM的类型安全特性:

import { eq, lte, max, and, subquery } from 'drizzle-orm';
import { db } from './your-db-connection';
import { A as a, A as innerA } from './schema';

const dayLuxonToBigint = 250n;

// 子查询:按name分组,获取每个name符合条件的最大last_updated
const maxUpdatedSubquery = db
  .select({
    name: innerA.name,
    maxUpdated: max(innerA.last_updated),
  })
  .from(innerA)
  .where(lte(innerA.last_updated, dayLuxonToBigint))
  .groupBy(innerA.name)
  .as('max_updated_sub');

// 关联子查询,匹配主表的对应记录
const result = await db
  .select({
    id: a.id,
    name: a.name,
    last_updated: a.last_updated,
  })
  .from(a)
  .innerJoin(maxUpdatedSubquery, eq(a.name, maxUpdatedSubquery.name))
  .where(eq(a.last_updated, maxUpdatedSubquery.maxUpdated));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:33:24