我正在尝试将以下SQL语句转换为JOOQ:
SELECT g.id, g.machine_id,
xmin.min_trans_id,
xmax.max_id
FROM machine_location_move_events g
, LATERAL
( SELECT c.ts AS min_ts, c.id AS min_id, c.transaction_id AS min_trans_id
FROM machine_economy_counters c
WHERE c.move_event_id = g.id
AND c.ts BETWEEN timestamp '2012-03-02 00:00:00'
AND timestamp '2014-03-05 12:00:00'
ORDER BY c.ts ASC
LIMIT 1
) xmin
, LATERAL
( SELECT c.ts AS max_ts, c.id AS max_id, c.transaction_id AS max_trans_id
FROM machine_economy_counters c
WHERE c.move_event_id = g.id
AND c.ts BETWEEN timestamp '2012-03-02 00:00:00'
AND timestamp '2014-03-05 12:00:00'
ORDER BY c.ts DESC
LIMIT 1
) xmax
WHERE xmin.min_ts IS NOT NULL ;
我的JOOQ java代码如下所示:
@Test
public void getTotalBetween() {
DateTime from = new DateTime(2012, 3, 2, 0, 0, DateTimeZone.forID("Europe/Copenhagen"));
DateTime to = new DateTime(2014, 3, 5, 12, 0, DateTimeZone.forID("Europe/Copenhagen"));
DSLContext dslContext = jooqProvider.getDSLContext();
SelectOffsetStep<Record3<Timestamp, Long, Long>> innerMinSelect;
{
MachineLocationMoveEvents gTable = MACHINE_LOCATION_MOVE_EVENTS.as("g");
MachineEconomyCounters cTable = MACHINE_ECONOMY_COUNTERS.as("c");
Field<Timestamp> min_ts = min(cTable.TS).as("min_ts");
Field<Long> min_id = cTable.ID.as("min_id");
Field<Long> min_transaction_id = cTable.TRANSACTION_ID.as("min_trans_id");
innerMinSelect = dslContext.select(min_ts, min_id, min_transaction_id)
.from(cTable)
.where(cTable.MOVE_EVENT_ID.eq(gTable.ID)
.and(cTable.TS.between(new Timestamp(from.getMillis()), new Timestamp(to.getMillis()))))
.orderBy(cTable.TS.asc())
.limit(1)
;
}
SelectOffsetStep<Record3<Timestamp, Long, Long>> innerMaxSelect;
{
MachineLocationMoveEvents gTable = MACHINE_LOCATION_MOVE_EVENTS.as("g");
MachineEconomyCounters cTable = MACHINE_ECONOMY_COUNTERS.as("c");
Field<Timestamp> max_ts = min(cTable.TS).as("max_ts");
Field<Long> max_id = cTable.ID.as("max_id");
Field<Long> max_transaction_id = cTable.TRANSACTION_ID.as("max_trans_id");
innerMaxSelect = dslContext.select(max_ts, max_id, max_transaction_id)
.from(cTable)
.where(cTable.MOVE_EVENT_ID.eq(gTable.ID)
.and(cTable.TS.between(new Timestamp(from.getMillis()), new Timestamp(to.getMillis()))))
.orderBy(cTable.TS.desc())
.limit(1)
;
}
MachineLocationMoveEvents gTable = MACHINE_LOCATION_MOVE_EVENTS.as("g");
MachineEconomyCounters cTable = MACHINE_ECONOMY_COUNTERS.as("c");
Field<Long> min_transaction_id = cTable.TRANSACTION_ID.as("min_trans_id");
Field<Long> max_id = cTable.ID.as("max_id");
Field<Timestamp> min_ts = min(cTable.TS).as("min_ts");
Table<Record3<Timestamp, Long, Long>> minLateral = lateral(innerMinSelect).as("xmin");
Table<Record3<Timestamp, Long, Long>> maxLateral = lateral(innerMaxSelect).as("xmax");
SelectConditionStep<Record4<Integer, Integer, Long, Long>> minMaxSelect = dslContext.select(gTable.ID, gTable.MACHINE_ID, minLateral.field(min_transaction_id), maxLateral.field(max_id))
.from(gTable, minLateral, maxLateral)
.where(minLateral.field(min_ts).isNotNull());
System.out.println(minMaxSelect.fetch());
}
但是,当我运行测试时,我会收到此错误消息:ERROR: column "c.id" must appear in the GROUP BY clause or be used in an aggregate function
完整错误:
org.jooq.exception.DataAccessException: SQL [select "g"."id", "g"."machine_id", "xmin"."min_trans_id", "xmax"."max_id" from "public"."machine_location_move_events" as "g", lateral (select min("c"."ts") as "min_ts", "c"."id" as "min_id", "c"."transaction_id" as "min_trans_id" from "public"."machine_economy_counters" as "c" where ("c"."move_event_id" = "g"."id" and "c"."ts" between cast(? as timestamp) and cast(? as timestamp)) order by "c"."ts" asc limit ? offset ?) as "xmin", lateral (select min("c"."ts") as "max_ts", "c"."id" as "max_id", "c"."transaction_id" as "max_trans_id" from "public"."machine_economy_counters" as "c" where ("c"."move_event_id" = "g"."id" and "c"."ts" between cast(? as timestamp) and cast(? as timestamp)) order by "c"."ts" desc limit ? offset ?) as "xmax" where "xmin"."min_ts" is not null]; ERROR: column "c.id" must appear in the GROUP BY clause or be used in an aggregate function
Position: 171
at org.jooq.impl.Utils.translate(Utils.java:1287)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:495)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:326)
Caused by: org.postgresql.util.PSQLException: ERROR: column "c.id" must appear in the GROUP BY clause or be used in an aggregate function
Position: 171
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2161)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1890)
错误消息中的SQL在格式化时看起来像这样:
select "g"."id", "g"."machine_id",
"xmin"."min_trans_id",
"xmax"."max_id"
from "public"."machine_location_move_events" as "g"
, lateral
( select min("c"."ts") as "min_ts", "c"."id" as "min_id", "c"."transaction_id" as "min_trans_id"
from "public"."machine_economy_counters" as "c"
where ("c"."move_event_id" = "g"."id"
and "c"."ts" between cast(? as timestamp)
and cast(? as timestamp))
order by "c"."ts" asc
limit ? offset ?
) as "xmin"
, lateral
( select min("c"."ts") as "max_ts", "c"."id" as "max_id", "c"."transaction_id" as "max_trans_id"
from "public"."machine_economy_counters" as "c"
where ("c"."move_event_id" = "g"."id"
and "c"."ts" between cast(? as timestamp)
and cast(? as timestamp))
order by "c"."ts" desc
limit ? offset ?
) as "xmax"
where "xmin"."min_ts" is not null
据我所知,这个SQL看起来非常像上面发布的那个,它直接在PostgreSQL 9.3.3服务器上运行时有效。
我的SQL语句不包含GROUP BY,那么为什么PostgreSQL驱动程序声明我需要它?
我在JOOQ声明中做错了吗?