我在数据库中有一个包含列 date_start
的表和 date_finish
.它是日期范围和 date_start <= date_finish
.
我的代码中也有日期范围作为类 Range(dateStart, dateFinish)
和 dateStart <= dateFinish
.
然后我想在数据库表记录中找到哪些日期范围与我的代码中的范围有交集(包括边框)。
我为这个条件编写了下一个生成 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?
最佳答案
合并 NOT
时到子表达式中,您反转所有比较(例如 =
变为 <>
和 >
变为 <=
)并交换 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'
当你说 only ranges in table completely included in range [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]
相交 [2016-01-01, 2016-01-04]
.
关于java - QueryDsl:使用 or() 和 not() 为条件生成错误的 sql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34369614/