我在数据库中有表date_start
和date_finish
。它的日期范围和date_start <= date_finish
。
我的代码中的日期范围也是Range(dateStart, dateFinish)
和dateStart <= dateFinish
。
然后我想在DB表记录中找到哪个日期范围有交集(包括边框),并且在我的代码中有范围。
我为此条件编写了下一个生成BooleanExpression的函数:
public static BooleanExpression dateRangeIntersection(Range<Date> range, TemporalExpression<Date> pathStart, TemporalExpression<Date> pathFinish) {
return pathStart.gt(range.getLast()).
or(pathFinish.lt(range.getFirst())).
not();
}
我希望得到下一个sql条件(示例日期范围从2016-01-01到2016-01-04):
SELECT * FROM table t WHERE NOT (t.date_start > '2016-01-04' OR t.date_finish < '2016-01-01')
结果是:
SELECT * FROM table t WHERE t.date_start <= '2016-01-04' AND t.date_finish >= '2016-01-01'
这种情况是错误的,因为当表中的范围完全包含在范围[2016-01-01,2016-01-04]中时,它只能用于一种情况。
我认为QueryDsl试图理解条件并重写它更简单。但在这种情况下,它会让它错误。
有没有人知道如何在querydsl或重写条件中禁用条件优化以获得预期的sql?
答案 0 :(得分:1)
将NOT
合并到子表达式时,会反转所有比较(例如=
变为<>
而>
变为<=
)并交换{{1 } vs AND
,所以这两个表达式是相同的:
OR
这正是你所拥有的。它做得很好。
您的情况变为:NOT (a > b OR c < d)
a <= b AND c >= d
当你说只有完全包含在范围t.date_start <= '2016-01-04' AND t.date_finish >= '2016-01-01'
中的表格中的范围可行时,你就错了。
尝试[2016-01-01, 2016-01-04]
:
[2015-10-25, 2016-01-02]
是的,按预期工作:t.date_start <= '2016-01-04' AND t.date_finish >= '2016-01-01'
`2015-10-25` <= '2016-01-04' AND `2016-01-02` >= '2016-01-01'
TRUE AND TRUE
与[2015-10-25, 2016-01-02]
相交。