使用当前仅返回一个

时间:2015-10-21 12:58:29

标签: sql oracle stored-procedures groupwise-maximum

我正在为我工​​作的公司开发一个考勤申请表。每位员工都将拥有一份分配给他们的“工作时间表”。此计划可能在数年和数年内保持不变,或者可能在一周内更改两次。所以我创建了一个如下表格。该表允许应用程序知道每个员工在任何给定日期有效的计划。表的列是: 1.主键(带自动增量触发器) 2.时间表的ID 3.员工的ID 4.时间表生效日期

C_ID  SCHEDULE_CID  USER_CID        EFFECTIVE_DATE
98    27            1188685432      15-OCT-15 00:00:00
100   25            1188685432      16-OCT-15 00:00:00
101   26            1188685432      18-OCT-15 00:00:00
102   27            1904229547      14-OCT-15 00:00:00
103   25            1904229547      19-OCT-15 00:00:00

因此,为了确定哪个时间表对任何给定日期的员工有效,我可以运行以下查询,这似乎返回了我想要的内容:

select Schedule_Cid, Effective_Date from Lei_Tas_People_Schedules
where Effective_Date = (select max(Effective_Date) from Lei_Tas_People_Schedules
where Lei_Tas_People_Schedules.User_Cid = '1188685432'
and Effective_Date <= '19-oct-2015');

在此示例中,将返回: 26 18-OCT-15 00:00:00

基于上面的例子,2015年10月19日,员工1188685432,ID 26的时间表生效。

问题是,我有时需要获得在给定日期对所有450名员工有效的计划。我的问题是:什么是最佳解决方案,将在给定日期返回所有员工的时间表(不运行上述查询450次 - 这似乎非常低效)?或者有更好的方法来设计我的数据结构来实现我想要的吗?

我考虑过存储过程,但似乎我需要一个光标,我听说应该避免使用它。无论如何我不是SQL大师,但我愿意学习。

非常感谢。

编辑:请原谅我,我可以看到我的上述选择查询存在缺陷。我的问题仍然是“如何在给定日期之前为所有450名员工返回有效的时间表?”

编辑:至于这可能是另一个问题的重复,我会说以下内容:我收到的这个问题的答案似乎与“可能重复”问题的答案不同。也许我的问题是一样的,但不会有其他答案值得保持这个问题吗?特别是因为他们似乎是正确的答案。我不知道SO协议,所以我默认那些知道的人。

2 个答案:

答案 0 :(得分:1)

select user_cid, Schedule_Cid, Effective_Date
from (
select user_cid, Schedule_Cid, Effective_Date, 
row_number() over(partition by user_cid order by effective_date desc) as rn
from Lei_Tas_People_Schedules) t
where rn = 1

您可以使用row_number函数,并为每个用户获取包含最新日期的相应行。

答案 1 :(得分:1)

您要做的是对您的记录进行排名,以便找到每个人的最佳记录(即最新记录)。您使用ROW_NUMBER执行此操作,为每个人记录编号,以便提供最新的#1。然后只保留那些。

select 
  user_cid,
  schedule_cid,
  effective_date
from
(
  select 
    user_cid,
    schedule_cid,
    effective_date, 
    row_number() over (partition by user_cid 
                       order by effective_date desc) as rn
  from lei_tas_people_schedules
  where effective_date <= date'2015-10-19'
)
where rn = 1;

顺便说一下,你可以用你自己的方法做同样的事情。只是,使用分析函数应该更好,因为你只读了一次表。

select * 
from lei_tas_people_schedules
where (user_cid, effective_date) in 
(
  select user_cid, max(effective_date) 
  from lei_tas_people_schedules
  where effective_date <= date'2015-10-19'
  group by user_cid
);