用jOOQ找到即将到来的生日

时间:2013-12-20 12:01:48

标签: java mysql sql date-arithmetic jooq

我正在尝试转换查找即将到来的生日的现有查询以使用jOOQ。我的原始查询 - 使用MySQL,有点简化 - 是

SELECT COUNT(*) 
FROM people 
WHERE
    DATE_ADD(people_dob, INTERVAL YEAR(CURDATE()) - YEAR(people_dob) YEAR) 
    BETWEEN CURDATE() and DATE_ADD( CURDATE(), INTERVAL 7 DAY)

我试图用jOOQ来表达它,但失败了。我和

一样接近
context
    .selectCount()
    .from(PEOPLE)
    .where(
        PEOPLE_DOB.add(year(currentTimestamp()).minus(year(PEOPLE_DOB)))
        .between(currentTimestamp()).and(currentTimestamp().add(7)));

不幸的是,这转化为

select count(*) 
from `people` 
where 
    date_add(`people`.`people_dob`, interval (extract(year from current_timestamp()) - extract(year from `people`.`people_dob`)) day) 
    between current_timestamp() and date_add(current_timestamp(), interval 7 day)

这里的查询中断了[DATE_ADD] [date_add]的expr_unit参数,我的原始查询是YEAR,但是jOOQ呈现的那个是DAY

如何将此查询翻译成jOOQ?我不太关心当前的格式,我只想了解如何获得相同的结果。

2 个答案:

答案 0 :(得分:3)

jOOQ的Field.add()方法受到Oracle对

的解释的启发
DATE + NUMBER

...其中NUMBER(如果IntegerDouble)是天数。您想要的是相当于在给定日期添加SQL标准INTERVAL YEAR TO MONTH。如果要添加常量间隔,可以通过使用jOOQ's YearToMonth interval type来实现。 YearToMonth类型也会扩展java.lang.Number,因此也可以直观地与Field.add()一起使用。

虽然可以通过现有的jOOQ 3.2 API生成这样的Field<YearToMonth>,但我相信你最好只使用普通的SQL,可能是通过创建一个可重用的方法:

public static <T extends java.util.Date> 
Field<T> dateInCurrentYear(Field<T> field) {
    return DSL.field("DATE_ADD({0}, INTERVAL YEAR(CURDATE()) - YEAR({0}) YEAR)",
                     field.getDataType(),
                     field);
}

这可能是#2727的有用功能添加......

不幸的是,各种SQL方言对日期时间算术的解释很难标准化。我们在那里不断改进,但通常,纯SQL是编写特定于方言的日期时间算术表达式的最佳方式。

答案 1 :(得分:1)

解决问题的一种方法是在where子句中使用String。我在这里写下来是为了完整,但我认为它错过了jOOQ

的观点
context.
    selectCount().
    from(PEOPLE).
    where("DATE_ADD(people_dob, INTERVAL YEAR(CURDATE()) - YEAR(people_dob) YEAR)" + 
        " BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE()").