简体   繁体   English

如何在 MikroORM 中运行 `union` SQL 命令

[英]How to run `union` SQL command in MikroORM

Also asked at GitHub .还询问了GitHub


I'd like to use union in MikroORM.我想在 MikroORM 中使用union There doesn't seem to be a built-in way (like qb.union() , therefore I think I either need to run a raw SQL command (via qb.raw() ) or use Knex to build the command.似乎没有内置方式(如qb.union() ,因此我认为我需要运行原始 SQL 命令(通过qb.raw() )或使用 Knex 构建命令。

For example, I want to get some rows from a table based on some condition, however, at any case, return at least two rows with the greatest ID.例如,我想根据某些条件从表中获取一些行,但是无论如何,至少要返回具有最大 ID 的两行。

(
  select * from sch.tbl
  -- where  -- insert some condition, e.g. `id > 10`
  order by id desc
) union (
  select * from sch.tbl order by id desc limit 2
) order by id asc;

which I presume can be accomplished with Knex like this:我认为这可以通过 Knex 完成,如下所示:

this.orm.em.getKnex()
  .union(qb => qb
    .select('*')
    .withSchema('sch')
    .from('tbl')
    .where('id', '>', 10)
    .orderBy('id', 'DESC')
    .limit(10)
  )
  .union(qb => qb
    .select('*')
    .withSchema('sch')
    .from('tbl')
    .orderBy('id', 'DESC')
    .limit(2)
  )
  .orderBy('id', 'ASC')

However, I have no idea how to get the result.但是,我不知道如何得到结果。

When I run the following:当我运行以下命令时:

qb.raw('(select * from ?.? where id > ? order by id desc limit 10) union (select * from ?.? order by id desc limit 2) order by id asc', ['sch', 'tbl', 10, 'sch', 'tbl'])

it builds a query (output of qb.getQuery() ) select "s0".* from "sch"."tbl" as "s0" , which is not what I wanted.它构建了一个查询( qb.getQuery()的输出) select "s0".* from "sch"."tbl" as "s0" ,这不是我想要的。

Thanks for your help!谢谢你的帮助!

Update更新

I can use the following, however, when I use ?但是,当我使用? placeholders, it fails as it replaces them with $1 ( 1 is incremented).占位符,它会失败,因为它用$1替换它们( 1递增)。 However, it works without the placeholders as expected.但是,它可以像预期的那样在没有占位符的情况下工作。

const knex = this.orm.em.getKnex()

// This fails
const result = await knex.raw('(select * from ?.? where id > ? order by id desc limit 10) union (select * from ?.? order by id desc limit 2) order by id asc', ['sch', 'tbl', 10, 'sch', 'tbl'])

// Error
error: (select * from $1.$2 where id > $3 order by id desc limit 10) union (select * from $4.$5 order by id desc limit 2) order by id asc - syntax error at or near "$1"

// This works
const x = await knex.raw('(select * from sch.tbl where id > 10 order by id desc limit 10) union (select * from sch.tbl order by id desc limit 2) order by id asc', ['sch', 'tbl', 10, 'sch', 'tbl'])

While I'd prefer some syntactic sugar commands (either in MikroORM or Knex), raw SQL commands are a good workaround, however, I want to use the placeholders (bindings).虽然我更喜欢一些语法糖命令(在 MikroORM 或 Knex 中),但原始 SQL 命令是一个很好的解决方法,但是,我想使用占位符(绑定)。 How can I accomplish that?我怎样才能做到这一点?


Update 2更新 2

Okay, I missed that note in the Knex docs that ?好吧,我错过了 Knex 文档中的那个注释? is interpreted as value and ??被解释为值和?? as identifier.作为标识符。

Furthermore, I've found a solution using Knex (albeit I use it from MikroORM):此外,我找到了一个使用 Knex 的解决方案(尽管我使用的是 MikroORM):

const knex = this.orm.em.getKnex()

const xKnexRaw = knex
  .withSchema('sch')
  .select('*')
  .from('tbl')
  .where('id', '>', 10)
  .orderBy('start_time', 'desc')
  .limit(10)
  .union(
    qb => qb
      .select('*')
      .withSchema('sch')
      .from('tbl')
      .orderBy('id', 'desc')
      .limit(2),
    true
  )
  .orderBy('start_time', 'asc')

// `res` is a result (array of row) without TypeScript types
const res = await this.orm.em.getConnection().execute(query)
// `entities` is a result (array of entities) with mapped TypeScript types
const entities = res.map(e => this.orm.em.map(StatusInterval, e))

This is a solution using Knex (albeit I use it from MikroORM):这是一个使用 Knex 的解决方案(尽管我使用的是 MikroORM):

const knex = this.orm.em.getKnex()

const query = knex
  .withSchema('sch')
  .select('*')
  .from('tbl')
  .where('id', '>', 10)
  .orderBy('start_time', 'desc')
  .limit(10)
  .union(
    qb => qb
      .select('*')
      .withSchema('sch')
      .from('tbl')
      .orderBy('id', 'desc')
      .limit(2),
    true
  )
  .orderBy('start_time', 'asc')

// `res` is a result (array of row) without TypeScript types
const res = await this.orm.em.getConnection().execute(query)
// `entities` is a result (array of entities) with mapped TypeScript types
const entities = res.map(e => this.orm.em.map(StatusInterval, e))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM