我希望能够返回从现在到指定时间间隔过生日的用户。
用户模型
我的时间间隔 = 30天
我的数据集
|---------------------|------------------|------------------|
| id | name | birthday |
|---------------------|------------------|------------------|
| 1 | Tim | 27/06/1994 |
|---------------------|------------------|------------------|
我的尝试
SELECT * FROM User where User.birthday BETWEEN NOW()::timestamp AND to_char(NOW() + interval '30 days','MM-DD')::timestamp;
返回
空。 Postgres假设通过省略我实际上意味着第1年的年份。
我想要什么
此查询返回生日所在的所有用户,无论年份如何。
尝试回答(非常感谢@Mureinik)
SELECT *
FROM user
WHERE birthday BETWEEN TO_CHAR(NOW(), 'MM-DD') AND
TO_CHAR(NOW() + INTERVAL '30 days','MM-DD')
此答案的问题
答案 0 :(得分:2)
我根据当前年份和用户的生日月份和日期生成了一个新日期,然后查看是否在接下来的30天内。
select *
from user
where date(date_part('year', current_date)||'-'||date_part('month', birthday)||'-'||date_part('day', birthday))
between current_date and current_date + interval '30 days';
例如:
# select * from user;
id | name | birthday
----+-------+------------
1 | Tim | 1994-06-27
2 | Steve | 1982-06-23
3 | Dave | 1980-07-29
(3 rows)
# select *
from user
where date(date_part('year', current_date)||'-'||date_part('month', birthday)||'-'||date_part('day', birthday))
between current_date and current_date + interval '30 days';
id | name | birthday
----+-------+------------
1 | Tim | 1994-06-27
2 | Steve | 1982-06-23
(2 rows)
答案 1 :(得分:0)
您可以将between
的参数转换为字符串并使用词典比较。由于格式是固定宽度,因此应该没问题:
SELECT *
FROM user
WHERE birthday BETWEEN TO_CHAR(NOW(), 'MM-DD') AND
TO_CHAR(NOW() + INTERVAL '30 days','MM-DD')
答案 2 :(得分:0)
这里,我在支持 QueryDsl 的项目中实现了什么:
private static final DateTimeFormatter DTF_MM_dd = DateTimeFormatter.ofPattern("MM-dd");
protected BooleanExpression betweenLocalDatesIgnoringYear(DatePath<LocalDate> localDate, LocalDate from, LocalDate to) {
if (from == null && to == null) {
return Expressions.asBoolean(true).isTrue();
}
if (Objects.equals(from, to)) {
return eqLocalDateIgnoringYear(localDate, from);
}
Set<String> MM_DDs = new HashSet<>();
for (LocalDate date = (from != null ? from : LocalDate.now());
date.isBefore(to != null ? to.plusDays(1) : from.plusMonths(1).plusDays(1));
date = date.plusDays(1)) {
MM_DDs.add(DTF_MM_dd.format(date));
}
if (MM_DDs.contains("02-28")) {
MM_DDs.add("02-29");
}
if (MM_DDs.isEmpty()) {
return Expressions.asBoolean(true).isTrue();
}
return localDateIgnoringYearIn(localDate, MM_DDs.stream().toArray(String[]::new));
}
protected BooleanExpression eqLocalDateIgnoringYear(DatePath<LocalDate> pathLocalDate, LocalDate localDate) {
if (localDate == null) {
return Expressions.asBoolean(true).isTrue();
}
return localDateIgnoringYearIn(pathLocalDate, DTF_MM_dd.format(localDate));
}
private BooleanExpression localDateIgnoringYearIn(DatePath<LocalDate> pathLocalDate, String... values) {
return Expressions.stringTemplate("FUNCTION('to_char', {0},'MM-DD')", pathLocalDate).in(values);
}