join联表
join联表提供5种连接方式(cross
、inner
、left
、right
、full
),但需要注意不同数据库的支持。使用_join()
函数创建JoinBuilder开始join联表操作:
template<typename... E>
JoinBuilder<E...> dao::_join<E...>();
模板参数列表传入参与join联表的所有表,其顺序决定了结果数据输出的顺序。通常,一个join查询具有以下基本形式:
select [字段列表] from [主表与别名] [连接类型] [字表与别名] on [连接条件] [查询条件] [输出限制]
设置输出字段
使用column()
函数设置各个表需要输出的字段值,忽略调用时将导致所有字段输出。
StudentTb::Field stuField;
TeacherTb::Field teaField;
ClassTb::Field clsField;
dao::_join<StudentTb, TeacherTb, ClassTb>()
.column(stuField.name, stuField.score, teaField.name)
.build().list();
与普通查询一样,column()
也可以联级调用,使用columnAll()
读出所有字段:
StudentTb::Field stuField;
TeacherTb::Field teaField;
ClassTb::Field clsField;
dao::_join<StudentTb, TeacherTb, ClassTb>()
.column(stuField.name, stuField.score)
.column(teaField.name)
.columnAll<ClassTb>()
.build().list();
设置主表
使用from()
函数设置查询主表:
StudentTb::Field stuField;
TeacherTb::Field teaField;
ClassTb::Field clsField;
dao::_join<StudentTb, TeacherTb, ClassTb>()
.column(stuField.name, stuField.score, teaField.name)
.from<StudentTb>()
.build().list();
设置字表连接类型与条件
5种连接类型用不同的函数调用:
crossJoin()
、innerJoin()
、leftJoin()
、rightJoin()
、fullJoin()
。使用on()
设置连接条件,这里on()
函数与普通select查询中filter
使用方式一样,不同的是,on()
函数中传入的条件可以是字段与字段之间的运算。
StudentTb::Field stuField;
TeacherTb::Field teaField;
ClassTb::Field clsField;
dao::_join<StudentTb, TeacherTb, ClassTb>()
.from<StudentTb>()
.innerJoin<TeacherTb>().on(teaField.id == stuField.teaId, teaField.room == 3)
.innerJoin<ClassTb>().on(clsField.id == stuField.clsId)
.build().list();
设置主查询条件
与普通select查询使用完全一样,使用filter()
函数设置主查询条件:
StudentTb::Field stuField;
TeacherTb::Field teaField;
ClassTb::Field clsField;
dao::_join<StudentTb, TeacherTb, ClassTb>()
.from<StudentTb>()
.innerJoin<TeacherTb>().on(teaField.id == stuField.teaId)
.innerJoin<ClassTb>().on(clsField.id == stuField.clsId)
.filter(stuField.score >= 90)
.build().list();
设置结果输出限制条件
同样的,使用with()
函数设置输出限制条件:
StudentTb::Field stuField;
TeacherTb::Field teaField;
ClassTb::Field clsField;
dao::_join<StudentTb, TeacherTb, ClassTb>()
.from<StudentTb>()
.innerJoin<TeacherTb>().on(teaField.id == stuField.teaId)
.innerJoin<ClassTb>().on(clsField.id == stuField.clsId)
.with(_orderBy(stuField.name.desc()))
.build().list();
查询结果的获取
使用list()
函数输出查询结果,其结果为QList列表:
template<typename... E>
QList<std::tuple<E...>> dao::_join().build().list();
其中,std::tuple
中的模板参数列表,正是_join<E...>()
函数出入的模板参数列表。读取结果示例如下:
StudentTb::Field stuField;
TeacherTb::Field teaField;
ClassTb::Field clsField;
auto result = dao::_join<StudentTb, TeacherTb, ClassTb>()
.column(stuField.name, stuField.score, teaField.name)
.from<StudentTb>()
.innerJoin<TeacherTb>().on(teaField.id == stuField.teaId, teaField.room == 3)
.innerJoin<ClassTb>().on(clsField.id == stuField.clsId)
.filter(stuField.score >= 90)
.with(_orderBy(stuField.name.desc()))
.build().list();
for (const auto& r : result) {
StudentTb dataStu = std::get<0>(r);
TeacherTb dataTea = std::get<1>(r);
ClassTb dataCls = std::get<2>(r);
//...
}
自连接
有时执行一个简单的递归查询时需要join表自己,这时,自定义一个类继承自dao::self<E>
类型进行一次重命名操作就能完成自连接:
class StudentTmp : public dao::self<StudentTb> {};
StudentTb::Field stuField;
StudentTmp::Field tmpField;
auto result = dao::_join<StudentTb, StudentTmp>()
.from<StudentTb>()
.innerJoin<StudentTmp>().on(tmpField.cls2Id == stuField.clsId)
.filter(stuField.score >= 90)
.build().list();