如何在 Knex 上使用 EXISTS 进行子查询?
Posted
技术标签:
【中文标题】如何在 Knex 上使用 EXISTS 进行子查询?【英文标题】:How can I make a subquery with EXISTS on Knex? 【发布时间】:2021-10-28 22:12:27 【问题描述】:我正在尝试使用 knex 构建查询,但在如何使用条件 EXISTS (SELECT * FROM caregiver_patient WHERE patient_id IN (0,1))
实现“WHERE”部分时遇到了很多麻烦。
这是关于 SQL 的原始查询:
SELECT * FROM users
JOIN caregivers ON users.id = caregivers.user_id
JOIN caregiver_schedule ON caregivers.id = caregiver_schedule.caregiver_id
JOIN caregiver_patient ON caregivers.id = caregiver_patient.caregiver_id
JOIN patients ON caregiver_patient.patient_id = patients.id
WHERE caregiver_schedule.week_day = 2
AND caregiver_schedule.from_time <= 1320
AND caregiver_schedule.to_time > 1320
AND EXISTS (SELECT * FROM caregiver_patient WHERE patient_id IN (0,1));
这是我目前使用 Knex 的代码:
const caregivers = await db("caregivers")
.whereExists(function ()
this.select("caregiver_schedule.*")
.from("caregiver_schedule")
.whereRaw("`caregiver_schedule`.`caregiver_id` = `caregivers`.`id`")
.whereRaw("`caregiver_schedule`.`week_day` = ??", [Number(week_day)])
.whereRaw("`caregiver_schedule`.`from_time` <= ??", [timeInMinutes])
.whereRaw("`caregiver_schedule`.`to_time` > ??", [timeInMinutes]);
)
.join("users", "caregivers.user_id", "=", "users.id")
.join("patients", "caregiver_patient.patient_id", "=", "patients.id")
.select([
"caregivers.*",
"users.*",
"caregiver_schedule.*",
"patients.*",
]);
原始查询中的所有数字都应该是变量。 IN
里面的数字应该是一个数组。
谁能帮我在 Knex 上完成这个查询?
【问题讨论】:
【参考方案1】:您提供的示例 knex 查询与原始 SQL 查询完全不相似,如果您想将原始 SQL 查询转换为 knex 查询,这就是它的样子:
const result = await db('users')
.innerJoin('caregivers', 'users.id', 'caregivers.user_id')
.innerJoin('caregiver_schedule', 'caregivers.id' 'caregiver_schedule.caregiver_id')
.innerJoin('caregiver_patient', 'caregivers.id', 'caregiver_patient.caregiver_id')
.innerJoin('patients', 'caregiver_patient.patient_id', 'patients.id')
.where('caregiver_schedule.week_day', Number(week_day))
.where('caregiver_schedule.from_time', '<=', timeInMinutes)
.where('caregiver_schedule.to_time', '>', timeInMinutes)
.whereExists(function()
this.select('*')
.from('caregiver_patient')
.whereIn('patient_id', [0,1]);
)
.select('*');
这假定db
变量是您的knex 连接。我还不得不猜测你想用哪些变量来替换原始 SQL 中的硬编码值,你可以随意用任何你喜欢的变量替换。
【讨论】:
感谢您的回答!另外,您知道我如何确保内部选择上的选定寄存器仅与当前寄存器相关(看护者)例如,我想要这样的东西:AND EXISTS (SELECT * FROM caregiver_patient WHERE patient_id IN (1) AND caregiver_id=caregivers.user_id);
我无法使用 knex
您应该能够将另一个.where
粘贴到whereExists
函数内的上述查询中,唯一的区别是当您想在where
子句中引用另一列时,您需要使用稍微不同的语法,否则它将尝试匹配字符串文字 "caregivers.user_id"
而不是列。有两种方法可以做到这一点,第一种是使用 .ref
,例如.where('caregiver_id', knex.ref('caregivers.user_id'));
,另一种选择是使用位置参数和 knex.raw 例如.where('caregiver_id', knex.raw('??', 'caregivers.user_id'));
.以上是关于如何在 Knex 上使用 EXISTS 进行子查询?的主要内容,如果未能解决你的问题,请参考以下文章