(优雅地)查询JPQL中的匹配天数

时间:2011-09-19 10:34:57

标签: java date jpa jpql

在我的一个项目中,我遇到以下情况:

我的“可用对象”具有开始日期结束日期。用户通过定义自己的日期范围来查询这些内容。

客户基本上希望输出所有可用性,并按可用性和用户日期范围的日期范围内匹配的天数对其进行排序。

例如,如果我有两个可用性,2012年1月1日至2012年1月31日可用性1 2012年1月1日 可用性2 直到 2012年1月15日并且用户查询“ 2012年1月1日 2012年1月31日之间的可用性”结果应为:

Availability   | numberOfDaysMatching
Availability 1 | 31
Availability 2 | 15

我无法真正理解如何在不对数据进行非规范化的情况下进行查询。作为Persistence API我正在使用JPA,由Hibernate提供(我认为是3.6ish)。

现在,我的解决方案是通过在每个商店/更新上计算它们并基本上将每一天存储在单独的表中来对可用性天数进行非规范化。通过这种方式,我可以通过基本计算用户查询中的天数来查询所需结果,在我的日历表中查找它们,然后查询其中一个日期为IN(:mycalculateddays)的可用性。

是否有一些非怪异的方法可以使用普通的JQPL来查询,而不像我那样对数据进行非规范化处理?

2 个答案:

答案 0 :(得分:1)

这会有用吗?

select *
from availabilities a
where
-- This is really least(a.end_date, :range_end) - greatest(a.start_date, :range_start)
-- I don't know if JPQL defines those functions so I implement it with CASE
(case when a.end_date <= :range_end then a.end_date else :range_end end) -
(case when a.start_date >= :range_start then a.start_date else :range_start end) > 0
order by 
(case when a.end_date <= :range_end then a.end_date else :range_end end) -
(case when a.start_date >= :range_start then a.start_date else :range_start end) desc

答案 1 :(得分:1)

查询重叠范围本身当然很容易(假设范围有效(两者的开始&lt; =结束):

SELECT r
FROM Range r 
WHERE  r.startDate <= :endDate and :startDate <= r.endDate

但是你不能构造一个计算两个日期之间差异的查询,因为JPQL不支持Date上的算术运算。此外,没有内置功能可以提供帮助。