我在使用Hibernate生成的SQL语句时遇到了一些麻烦。我想让所有用户在给定的时间范围内或特定的一天内过生日。虽然特定日期的声明工作正常,但另一个只返回前n个用户,其中n是正确用户的数量。
考虑这些数据:
ID name birthdate
1 firstUser 12.07.1990
2 user1 25.04.2007
3 user2 15.05.1992
4 user3 01.04.1988
首先是特定日期的生成语句:
select
*
from
( select
distinct *
from
USERS user0_
where
calculateNextBirthday(user0_.birthDate) = TO_DATE('25.04.2018', 'dd.MM.yyyy')
order by
user0_.id asc )
where
rownum <= ?; // This will be the row count of this statement with the same where clause, i.e. 1 if there is only 1 matching user
正如我所说,这句话会返回正确的用户(user1,ID为2
)。
与之间的相同陈述:
select
*
from
( select
distinct *
from
USERS user0_
where
calculateNextBirthday(user0_.birthDate) between TO_DATE('01.04.2018', 'dd.MM.yyyy') and TO_DATE('30.04.2018', 'dd.MM.yyyy')
order by
user0_.id asc )
where
rownum <= ?; // This will be the row count of this statement with the same where clause, i.e. 1 if there is only 1 matching user
此声明有一种奇怪的行为。如果我执行内部select语句,结果将包含正确的用户(user1
)。但是执行整个语句它将返回第一个用户(firstUser
ID为1
)。像这样更改日期:
select
*
from
( select
distinct *
from
USERS user0_
where
calculateNextBirthday(user0_.birthDate) between TO_DATE('01.04.2018', 'dd.MM.yyyy') and TO_DATE('30.06.2018', 'dd.MM.yyyy')
order by
user0_.id asc )
where
rownum <= ?; // This will be the row count of this statement with the same where clause, i.e. 1 if there is only 1 matching user
将返回前两个用户(firstUser
和user1
),因为有两个匹配的用户(user1
和user2
)
如果我从外部语句中删除rownum,它只返回正确的用户(下面的示例返回user1
)。
select
*
from
( select
distinct *
from
USERS user0_
where
calculateNextBirthday(user0_.birthDate) between TO_DATE('01.04.2018', 'dd.MM.yyyy') and TO_DATE('30.04.2018', 'dd.MM.yyyy')
order by
user0_.id asc )
所以我不知道Oracle在哪里获得第一个用户条目。
我在这里做错了什么,或Oracle Oracle数据库10g快捷版10.2.0.1.0中是否有错误?
答案 0 :(得分:1)
似乎适合我(11g)。我不会使用你的calculateNextBirthday函数:
SQL> drop table t_users
Table dropped.
SQL> create table t_users
(
id number,
name varchar2(100),
birthdate date
)
Table created.
SQL> insert into t_users (id,name,birthdate) values (1,'firstUser',to_date('12.07.1990','DD.MM.YYYY'))
1 row created.
SQL> insert into t_users (id,name,birthdate) values (2,'user1',to_date('25.04.2007','DD.MM.YYYY'))
1 row created.
SQL> insert into t_users (id,name,birthdate) values (3,'user2',to_date('15.05.1992','DD.MM.YYYY'))
1 row created.
SQL> insert into t_users (id,name,birthdate) values (4,'user3',to_date('01.04.1988','DD.MM.YYYY'))
1 row created.
SQL> commit
Commit complete.
SQL> select
*
from
( select
distinct *
from
t_users user0_
where
to_date( to_char(birthdate, 'DD.MM') || '.' || to_char(sysdate, 'YYYY'), 'DD.MM.YYYY' ) between TO_DATE('01.04.2018', 'dd.MM.yyyy') and TO_DATE('30.04.2018', 'dd.MM.yyyy')
order by
user0_.id asc )
where
rownum <= 2
ID
----------
NAME
--------------------------------------------------------------------------------
BIRTHDATE
---------
2
user1
25-APR-07
4
user3
01-APR-88
2 rows selected.
答案 1 :(得分:0)
在这种情况下你不能依赖rownum,因为order by在内部选择中。 Rownum正在确定之前,因此也是一般的。一般来说,依靠rownum并不是一个好习惯。
有一点需要注意,我知道Oracle SQL并且我并不熟悉Hibernate,我的建议是以下:
我会考虑用你需要的信息创建一个视图,看看Hibernate是否能更好地处理它,否则我会试着用一个只使用内部选择的Hibernate生成的SQL语句来覆盖它,因为它没有Oracle有理由使用outer语句包装该选择。