如何将查询用户最近预约的MySQL语句转换为TypeORM查询
将MySQL查询转换为TypeORM实现
前提假设
已定义好对应的TypeORM实体:
User实体对应users表,包含与Reservation的一对多关联Reservation实体对应reservations表,包含与User的多对一关联
方法一:直接对应原SQL的QueryBuilder写法
这种写法完全复刻你给出的MySQL逻辑,通过leftJoinAndSelect实现左连接,并在连接条件中嵌入子查询:
import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { User } from './user.entity'; @Injectable() export class UserService { constructor( @InjectRepository(User) private readonly userRepository: Repository<User>, ) {} async getUsersWithNextReservation() { return this.userRepository .createQueryBuilder('u') .leftJoinAndSelect( 'reservations', 'r', `u.id = r.user_id AND r.start_date = ( SELECT MIN(r2.start_date) FROM reservations r2 WHERE r2.user_id = r.user_id AND r2.start_date >= CURRENT_TIMESTAMP() AND r2.status = :status )`, { status: 'OPEN' } ) .getMany(); } }
方法二:拆分式子查询的写法
如果希望子查询逻辑更清晰,可将子查询单独构建后嵌入主查询:
async getUsersWithNextReservation() { // 构建子查询:获取每个用户的下一个有效预约时间 const nextReservationSubQuery = this.userRepository .createQueryBuilder('r2') .select('MIN(r2.start_date)') .where('r2.user_id = r.user_id') .andWhere('r2.start_date >= CURRENT_TIMESTAMP()') .andWhere('r2.status = :status', { status: 'OPEN' }); return this.userRepository .createQueryBuilder('u') .leftJoinAndSelect( 'reservations', 'r', `u.id = r.user_id AND r.start_date = (${nextReservationSubQuery.getQuery()})`, nextReservationSubQuery.getParameters() ) .getMany(); }
说明
- 两种写法都能实现原SQL的效果:返回所有用户,每个用户附带其下一个状态为
OPEN且未开始的最近预约(无符合条件预约时,reservations字段为null) - 使用参数化的
:status避免SQL注入风险 - 若需返回特定字段而非
*,可在createQueryBuilder后添加.select(['u.id', 'u.name', 'r.start_date', 'r.id'])等指定字段
内容的提问来源于stack exchange,提问作者Felipe K. Bernardino
相关产品推荐
相关产品推荐

