我在数据库中有一个表,其中包含如下所示的记录:
Id | EmpName | LeaveDate | createdDate
1 | Govind | 2014-04-02 00:00:00.000 | 2014-04-02
2 | Aravind | 2014-04-03 00:00:00.000 | 2014-04-05
3 | Govind | 2014-04-04 00:00:00.000 | 2014-04-10
4 | Amar | 2014-04-05 00:00:00.000 | 2014-04-11
6 | Aravind | 2014-04-06 00:00:00.000 | 2014-04-16
7 | Govind | 2014-04-07 00:00:00.000 | 2014-04-16
8 | Aravind | 2014-04-08 00:00:00.000 | 2014-04-16
9 | Amar | 2014-04-09 00:00:00.000 | 2014-04-16
10 | Aravind | 2014-04-10 00:00:00.000 | 2014-04-16
11 | Govind | 2014-04-11 00:00:00.000 | 2014-04-16
12 | Aravind | 2014-04-12 00:00:00.000 | 2014-04-16
13 | Amar | 2014-04-13 00:00:00.000 | 2014-04-16
14 | Aravind | 2014-04-14 00:00:00.000 | 2014-04-16
现在,我希望显示所有员工的最后两条记录
示例输出:
Id | EmpName | LeaveDate | createdDate
11 | Govind | 2014-04-11 00:00:00.000 | 2014-04-16
7 | Govind | 2014-04-07 00:00:00.000 | 2014-04-16
14 | Aravind | 2014-04-14 00:00:00.000 | 2014-04-16
12 | Aravind | 2014-04-12 00:00:00.000 | 2014-04-16
13 | Amar | 2014-04-13 00:00:00.000 | 2014-04-16
9 | Amar | 2014-04-09 00:00:00.000 | 2014-04-16
使用JPA时,难以撰写以下要求的查询。任何人帮助我
答案 0 :(得分:2)
sql-server
。
使用CTE
。
;with cte as
(
select rn = row_number() over
(
partition by EmpName
order by LeaveDate desc
),*
from employees
)
select * from cte
where rn <= 2;
mysql
。
添加一个rownumber。
select t2.Id,
t2.EmpName,
t2.LeaveDate,
t2.createdDate
from
(
select Id,
EmpName,
LeaveDate,
createdDate,
(
case EmpName
when @curA
then @curRow := @curRow + 1
else @curRow := 1 and @curA := EmpName end
) + 1 as rn
from employees t,
(select @curRow := 0, @curA := '') r
order by EmpName,LeaveDate desc
)t2
where t2.rn<3;
以下sql查询适用于mysql
和sql-server
。
<强>查询强>
select *
from employees t1
where
(
select count(*) from employees t2
where t2.EmpName = t1.EmpName
and t2.LeaveDate > t1.LeaveDate
) <= 1
order by t1.EmpName;
答案 1 :(得分:2)
在JPA(JPQL)中,无法以一般而有效的方式解决此问题。 Rownum
概念在数据库中是如此不同,以至于JPQL无法用不同的方言对其进行建模。
Here is one answer为整个结果集提供了一种解决方法,但这对子查询不起作用。 This answer讲述了同样的故事,但他们没有提出解决方案。
这是一个JPQL解决方案,在大型表格上可能效率低下(除非您正确索引表格):
SELECT e1.EmpName, e1.LeaveDate, e1.createdDate
FROM EmployeeLeaves e1
JOIN EmployeeLeaves e2 on (e1.EmpName = e2.EmpName)
WHERE e1.LeaveDate >= e2.LeaveDate
GROUP BY e1.EmpName, e1.LeaveDate, e1.createdDate
HAVING count(*) <= 2
另一种(效率低下)可能的解决方案是逐个查询每个员工并用Java处理结果。
答案 2 :(得分:1)
这是一个SQL Server查询:
SELECT t.Id, t.EmpName, t.LeaveDate, t.createdDate
FROM
(
SELECT Id, EmpName, LeaveDate, createdDate, RANK() OVER
(PARTITION BY LeaveDate ORDER BY LeaveDate) num
FROM Table
) t
WHERE t.num <= 2
答案 3 :(得分:1)
使用以下适用于Sql Server的查询
jQuery(document).ready(function() {
jQuery('li').click(function(evt) {
evt.preventDefault();
var id = jQuery(this).attr("value");
jQuery('.clickedId').append(id+'<br>');
});
});
答案 4 :(得分:0)
在SQL server中尝试此查询
WITH tmp
AS
(
SELECT id
,Empname
,Leavedate
,CreatedDate
,DENSE_RANK() OVER (PARTITION BY Empname ORDER BY Leavedate) AS [rank_leavedate]
FROM tbl
)
SELECT *
FROM tmp
WHERE tmp.rank_leavedate IN (1,2)
答案 5 :(得分:0)
在SQL Server上Row_Number() function with Partition By子句是此类查询的最佳选择
以下是SELECT
示例with cte as (
select
rn = ROW_NUMBER() over (partition by EmpName order by LeaveDate desc),*
from EmployeeLeaves
)
select
Id,
EmpName,
LeaveDate,
createdDate
from cte
where rn <= 2
答案 6 :(得分:-4)
由于您提供的数据看起来像虚拟数据,我会重新设计数据库,使其具有主数据,其中包括以下内容: 员工ID,员工名,员工姓,登录密码......
另一张桌子可以用来: 员工ID,startdate,leavedate
这两个表将在员工ID
上相互附加你将有两个while循环,一个在另一个循环中: 第一个sql语句看起来类似于:
SELECT * from TBL1
从开始,您将为表2的查询设置变量名称
第二次使用的SQL看起来类似于:
SELECT * FROM tbl where employee_id (from table 1)= employee_id (from table 1) LIMIT 2
这个解决方案的优势在于,如果您正在进行数百万条记录,那么员工数据将从一开始就保持独立,并留出时间来节省大量存储空间。