jooq嵌套选择并输入安全性

时间:2019-06-13 15:27:05

标签: java sql jooq

我正在尝试在jooq中编写以下sql:

SELECT SUM(`sum`) AS `total`
FROM(
        SELECT
        MIN(`num_views`) AS `sum`
        FROM `fact_wishlist`
        GROUP BY `id`
) AS t

我发现了一些与此相关的东西:

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();

但是,我却以某种方式失去了类型安全性。我觉得我做错了明显的事,但是我没有看到。关于如何改善它的任何想法?

1 个答案:

答案 0 :(得分:1)

不幸的是,您无法使用jOOQ中的派生表实现100%类型安全,因为Java编译器无法真正证明派生表包含一列。但是通过重用"views"字段,绝对可以提高您的使用率。只需将其分配给局部变量即可。

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();

请注意,假设您传入的字段确实以其给定名称存在于派生表中,并且Table.field(Field<T>)方法如何允许维护<T>类型引用。参数字段。

使用窗口函数的替代方法

请注意,可以使用window functions如下重写查询。

SELECT SUM(MIN(num_views)) OVER ()
FROM fact_wishlist
GROUP BY id
LIMIT 1

或者在jOOQ中:

return
create.select(sum(min(MYTABLE.NUM_VIEWS)).over())
      .from(MYTABLE)
      .groupBy(MYTABLE.ID)
      .limit(inline(1))
      .fetchSingle()
      .value1().longValue();

这当然取决于您的数据库是否支持窗口功能,它可能比双重聚合解决方案快/慢,具体取决于供应商。