对于标识为id
的特定数据库条目,请考虑数据库中的日期间隔,从BEGIN_DATE
到END_DATE
,表示为(BEGIN_DATE
,{{ 1}})。
鉴于两个新日期构成了区间(END_DATE
,newBeginDate
),我必须更新(newEndDate
,BEGIN_DATE
),以便生成的区间包含全部4日期。换句话说,我想添加两个区间(因为我添加它们,结果区间可能保持不变或增长,但从不收缩)。
举几个例子:
如果(END_DATE
,BEGIN_DATE
)=(END_DATE
,January 10
),则:
(January 20
,BEGIN_DATE
)+(END_DATE
,Jan 15
)=(Jan 25
,Jan 10
)
(Jan 25
,BEGIN_DATE
)+(END_DATE
,Jan 05
)=(Jan 15
,Jan 05
)
(Jan 20
,BEGIN_DATE
)+(END_DATE
,Jan 05
)=(Jan 25
,Jan 05
)
(Jan 25
,BEGIN_DATE
)+(END_DATE
,Jan 15
)=(Jan 15
,Jan 10
)
(Jan 20
,BEGIN_DATE
)+(END_DATE
,Jan 10
)=(Jan 13
,Jan 10
)
以下两个查询共同实现了这一目标。第一个更新Jan 20
,第二个更新BEGIN_DATE
:
END_DATE
我的问题是: 如何在单个查询中执行此操作?
答案 0 :(得分:1)
当涉及到更复杂的编程结构时,SQL是有限的,所以既然你使用Hibernate我就会读取约会实体实例并更新它的字段。这将需要两个查询,一个用于读取,一个用于更新,但它仍然只是一个更新语句,并且是最易读的解决方案。
如果您仍然只需要一个更新语句而不需要其他任何内容,则可以使用case
将您的两个语句合并为一个:
update APPOINTMENTS
set BEGIN_DATE = case when (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) then :newBeginDate else BEGIN_DATE end,
END_DATE = case when (END_DATE is null or END_DATE < :newEndDate) then :newEndDate else END_DATE end
where (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate or END_DATE is null or END_DATE < :newEndDate)
and ID = :id
答案 1 :(得分:1)
使用LEAST()
和GREATEST()
功能。对于NULL,请使用COALESCE()
。
update APPOINTMENTS
set BEGIN_DATE = coalesce(least(BEGIN_DATE, :newBeginDate), :newBeginDate),
END_DATE = coalesce(greatest(END_DATE, :newEndDate), :newEndDate)
where ID = :id
我认为最不可能并不需要解释。如果旧日期为NULL,COALESCE将选择新日期。因此,在WHERE子句中不需要除ID = :id
之外的任何条件。