如何将带子查询的SQL转为Drift语法(无需自定义查询)及子查询位置
将目标SQL转换为Drift语法的实现
原SQL逻辑拆解
原SQL通过两次左连接实现:先分组activities拿到每个tracker的最新活动结束时间,再关联trackers表,最后通过子查询结果匹配到对应的最新活动记录。
Drift代码改造(含子查询位置)
子查询需要作为第一个关联项,放在trackers和activities的连接之间,完整代码如下:
// 1. 构建原SQL中的子查询:获取每个tracker的最新活动结束时间 final subquery = selectOnly(activities) ..addColumns([ activities.tracker, activities.end.max().alias('latest_activity_date'), ]) ..groupBy([activities.tracker]); // 2. 主查询:依次关联trackers、子查询、activities final query = select(trackers).join([ // 第一步左连接子查询,对应原SQL的第一个LEFT JOIN leftOuterJoin( subquery.as('subquery'), subquery['tracker'].equalsExp(trackers.id), ), // 第二步左连接activities,对应原SQL的第二个LEFT JOIN leftOuterJoin( activities, activities.tracker.equalsExp(subquery['tracker']) & activities.end.equalsExp(subquery['latest_activity_date']), ), ]) // 对应原SQL的ORDER BY a."end" ..orderBy([OrderingTerm.desc(activities.end)]); // 执行查询并转换结果 query.get().then((rows) => rows.map((row) { final tracker = row.readTable(trackers); // 左连接可能返回null,用readTableOrNull更严谨 final latestActivity = row.readTableOrNull(activities); return TrackerWithLatestActivity(tracker, latestActivity); }).toList());
关键说明
- 子查询通过
selectOnly构建,只选择需要的字段,用.max()聚合函数实现MAX(activities."end"),.alias()对应SQL中的字段别名。 - 主查询的join顺序严格对应原SQL:先关联
trackers和子查询,再通过子查询的结果关联到对应的最新activities记录。 - 因为是左连接,
activities可能没有匹配记录,所以用readTableOrNull替代readTable避免空指针问题。
内容的提问来源于stack exchange,提问作者Bang Dida
相关产品推荐
相关产品推荐

