我正在使用QueryDSL构建一个SQL查询,该查询包含在联合中连接的多个子查询。这是我的查询的基础:
QTransaction t = QTransaction.transaction;
query = query.from(t).where(t.total.gt(BigDecimal.ZERO));
然后我有几个子查询来获取与事务关联的客户端名称。我已经减少了两个例子:
SQLSubQuery subQuery = new SQLSubQuery();
subQuery = subQuery.from(t).join(t.fk462bdfe3e03a52d4, QClient.client);
ListSubQuery clientByPaid = subQuery.list(t.id, bt.paidId, QClient.client.name.as("clientname"));
subQuery = new SQLSubQuery();
subQuery = subQuery.from(t).where(t.paidId.isNull(), t.clientname.isNotNull());
ListSubQuery clientByName = subQuery.list(t.id, Expressions.constant(-1L), t.clientname.as("clientname"));
如何将这些组合在一起,并使用我的主查询加入联合?这是我目前的尝试:
subQuery = new SQLSubQuery();
subQuery = subQuery.from(subQuery.unionAll(clientByPaid,clientByName).as("namequery"));
query = query.leftJoin(subQuery.list(
t.id, Expressions.path(Long.class, "clientid"),
Expressions.stringPath("clientname")),
Expressions.path(List.class, "namequery"));
这会编译,但在我尝试query.count()
时会在运行时生成无效的SQL。可能的错误:
.as(...)
表达式与leftJoin
中使用的路径表达式之间的连接。答案 0 :(得分:8)
修正了它。主要的错误是我错过了左连接中的on
子句,但是为了表达on
条件,我必须更加小心命名子查询。文档对构造访问子查询结果的路径有点了解,所以这是示例。
union中的第一个查询设置列名:
SQLSubQuery subQuery = new SQLSubQuery();
subQuery = subQuery.from(t).join(t.fk462bdfe3e03a52d4, QClient.client);
ListSubQuery clientByPaid = subQuery.list(t.id.as("id"), t.paidId.as("clientid"),
QClient.client.name.as("clientname"));
subQuery = new SQLSubQuery();
subQuery = subQuery.from(t).where(t.paidId.isNull(), t.clientname.isNotNull());
ListSubQuery clientByName = subQuery.list(t.id, Expressions.constant(-1L),
t.clientname);
我现在需要构建一个路径表达式来引用我的内部查询。我在路径中使用哪个类似乎并不重要,所以我选择了Void来强调这一点。
subQuery = new SQLSubQuery();
Path innerUnion = Expressions.path(Void.class, "innernamequery");
subQuery = subQuery.from(subQuery.union(clientByPaid,clientByName).as(innerUnion));
表达on
子句的另一个路径表达式。请注意,我加入了联合查询的list()
,并使用之前定义的innerUnion
路径选择了每个列。
Path namequery = Expressions.path(Void.class, "namequery");
query = query.leftJoin(subQuery.list(
Expressions.path(Long.class, innerUnion, "id"),
Expressions.path(Long.class, innerUnion, "clientid"),
Expressions.stringPath(innerUnion, "clientname")),
namequery)
.on(t.id.eq(Expressions.path(Long.class, namequery, "id")));