Finding upcoming birthdays with jOOQ

雨燕双飞 提交于 2019-12-02 04:50:42

问题


I'm trying to convert an existing query which looks for upcoming birthdays to use jOOQ. My original query - using MySQL, and a bit simplified - is

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)

I tried to express it using jOOQ but failed. I got as close as

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

Unfortunately, that translates to

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)

What breaks the query here is the expr_unit argument for [DATE_ADD][date_add], which is my original query is YEAR, but in the one rendered by jOOQ is DAY.

How can I translate this query into jOOQ? I don't care much about the current format, I just want to understand how to get the same result.


回答1:


jOOQ's Field.add() method is inspired by Oracle's interpretation of

DATE + NUMBER

... where NUMBER (if an Integer or Double) is a number of days. What you want is the equivalent of adding a SQL standard INTERVAL YEAR TO MONTH to a given date. This could be achieved through using jOOQ's YearToMonth interval type, if you wanted to add a constant interval. The YearToMonth type also extends java.lang.Number, and can thus also be used with Field.add(), intuitively.

While it might be possible to generate such a Field<YearToMonth> through existing jOOQ 3.2 API, I believe that you will be better off to just resort to plain SQL, possibly by creating a reusable method:

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

This might be a useful feature addition for #2727 as well...

Unfortunately, the various SQL dialects' interpretations of date time arithmetic is hard to standardise. We're constantly improving things there, but often, plain SQL is the best way to write dialect-specific date time arithmetic expressions.




回答2:


One way of solving the issue is using a String in the where clause. I'm writing it down here for completeness, but I think it misses the point of 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()").


来源:https://stackoverflow.com/questions/20703229/finding-upcoming-birthdays-with-jooq

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!