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

PostgreSQL子查询关联语法错误:如何用Knex构建正确查询?

如何用Knex构建带distinct on的PostgreSQL左连接查询?

我有一段可正常运行的PostgreSQL查询语句:

select * from "A" left join (
    select distinct on ("provider_id") * from "B" order by "provider_id" asc, "date" desc
) B using ("provider_id") where "A"."date" >= '2022-02-17T08:31:46.781Z' order by "A"."date" desc limit 25;

尝试用Knex的.leftJoin方法构建查询:

query
  .orderBy("date", orderBy.sort)
  .limit(Math.min(limit, 1000))
  .offset(Math.min(offset, 100000))
  .leftJoin(
    this.db('B')
     .distinctOn('provider_id')
     .select('*')
     .orderBy([
       {
         column: 'provider_id',
       },
       {
         column: 'date',
         order: 'desc',
       },
    ]),
    'A.provider_id',
    'B.provider_id'
  )

也试过结合.raw的方式:

query
  .orderBy("date", orderBy.sort)
  .limit(Math.min(limit, 1000))
  .offset(Math.min(offset, 100000))
  .leftJoin(
    this.db.raw('select distinct on ("provider_id") * from "B" order by "provider_id", "date" desc'),
    'A.provider_id',
    'B.provider_id'
  )

但生成的SQL语句缺少子查询的括号和别名,导致语法错误:

select * from "A" left join select distinct on ("provider_id") * from "B" order by "provider_id", "date" desc on "A"."provider_id" = "B"."provider_id" where "date" >= '2022-02-17T09:09:08.148Z' order by "date" desc limit 25

执行时抛出错误:

ERROR:  syntax error at or near "select"
LINE 62: select * from "A" left join select distinct on ("provid...
                                          ^
SQL state: 42601
Character: 3951

解决方法

方法1:给Knex子查询添加.as()别名

Knex中,子查询需要用.as()指定别名,框架会自动给子查询加上括号并包裹别名。修改后的代码如下:

query
  .where('A.date', '>=', '2022-02-17T08:31:46.781Z')
  .orderBy('A.date', 'desc')
  .limit(25)
  .leftJoin(
    this.db('B')
     .distinctOn('provider_id')
     .select('*')
     .orderBy([
       { column: 'provider_id' },
       { column: 'date', order: 'desc' }
     ])
     .as('B'), // 关键:添加as('B')指定别名
    'A.provider_id',
    'B.provider_id'
  );

方法2:在raw语句中手动添加括号和别名

如果用.raw的方式,需要自己给子查询加上括号并指定别名,Knex不会自动处理这部分:

query
  .where('A.date', '>=', '2022-02-17T08:31:46.781Z')
  .orderBy('A.date', 'desc')
  .limit(25)
  .leftJoin(
    this.db.raw('(select distinct on ("provider_id") * from "B" order by "provider_id", "date" desc) B'), // 手动加括号和别名B
    'A.provider_id',
    'B.provider_id'
  );

两种方法生成的SQL都会和原始的正确语句一致,解决语法错误问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 05:33:57