如何为每位员工获得最多两条记录

时间:2015-09-22 05:56:28

标签: mysql sql sql-server oracle top-n

我在数据库中有一个表,其中包含如下所示的记录:

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时,难以撰写以下要求的查询。任何人帮助我

7 个答案:

答案 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;

SQL Fiddle

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 Fiddle

以下sql查询适用于mysqlsql-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

这个解决方案的优势在于,如果您正在进行数百万条记录,那么员工数据将从一开始就保持独立,并留出时间来节省大量存储空间。