Reputation: 266
I'm trying to write the following sql in jooq:
SELECT SUM(`sum`) AS `total`
FROM(
SELECT
MIN(`num_views`) AS `sum`
FROM `fact_wishlist`
GROUP BY `id`
) AS t
I've found something that works with this:
Table<Record2<String, Integer>> nested =
table(create.select(MYTABLE.ID,
min(MYTABLE.NUM_VIEWS)
.as("views"))
.from(MYTABLE)
.groupBy(MYTABLE.ID));
return create.select(sum((Field<Integer>) nested.field("views")))
.from(nested)
.fetchOne().value1().longValue();
However, somehow I've lost the type safety. I feel I'm doing something obvious wrong, but I'm not seeing it. Any ideas on how this could be improved?
Upvotes: 3
Views: 596
Reputation: 221145
Unfortunately, you cannot achieve 100% type safety with derived tables in jOOQ, as the Java compiler cannot really prove that a derived table contains a column. But your usage can definitely be improved by reusing the "views"
field. Just assign it to a local variable.
Field<Integer> views = min(MYTABLE.NUM_VIEWS).as("views");
Table<Record2<String, Integer>> nested =
table(create.select(MYTABLE.ID, min(views))
.from(MYTABLE)
.groupBy(MYTABLE.ID));
return create.select(sum(nested.field(views)))
.from(nested)
.fetchOne().value1().longValue();
Notice how the Table.field(Field<T>)
method allows for maintaining the <T>
type reference assuming that the field you pass in really exists in the derived table, by its given name, and that it matches the type of your argument field.
Notice that your query could be rewritten using window functions as follows.
SELECT SUM(MIN(num_views)) OVER ()
FROM fact_wishlist
GROUP BY id
LIMIT 1
Or in jOOQ:
return
create.select(sum(min(MYTABLE.NUM_VIEWS)).over())
.from(MYTABLE)
.groupBy(MYTABLE.ID)
.limit(inline(1))
.fetchSingle()
.value1().longValue();
This of course depends on whether your database supports window functions, and it might be faster/slower than your double aggregation solution, also depending on the vendor.
Upvotes: 2