[英]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.