【问题标题】:OracleSQL: Assigning employees to groups with date values, querying current assignments by dateOracle SQL:将员工分配到具有日期值的组,按日期查询当前分配
【发布时间】:2026-01-03 07:15:01
【问题描述】:

我有一个数据库,其中包含可以分配给组(另一个表)的员工(一个表)。 Bother 与另一个表employee-to-group 连接在一起,其中列出了组ID、员工ID 和分配的开始日期。

始终必须将员工分配到一个组,但分配可能每天都在变化。一名员工可能在 A 组工作一天,然后一周后转到 B 组并在 C 组工作。

我的任务是找出在任何给定日期哪些员工被分配到由其名称给出的某个组。所以输入应该是:组名、日期,我希望输出是在给定时刻属于该组的所有员工的数据。

这是一个包含一些测试数据的 SQL 小提琴: http://sqlfiddle.com/#!9/6d0bb

我用 mysql-statements 重新创建了数据库,因为我无法弄清楚 oracle 语句,对不起。

从测试数据中可以看出,有些员工可能永远不会更换组,而另一些则经常更换。还有一些员工计划在未来改变工作。查询必须考虑到这一点。

由于该应用程序是旧版应用程序,因此值(尤其是日期字段中的值)是有问题的。它们以“自 1990 年 1 月 1 日以来的天数”给出,因此条目“9131”表示“2015 年 1 月 1 日”。 9468 是今天 (2015-12-04),9496 是 2016-01-01)。

我已经拥有的是用于找出任何给定日期的“日期值”的代码,我称之为我正在使用的应用程序的“旧格式”(这里我刚刚使用了 CURRENT_DATE):

SELECT FLOOR(CURRENT_DATE - TO_DATE('1990-01-01', 'YYYY-MM-DD')) AS diffdate

为了找出某个员工被分配到哪个组,我尝试了:

SELECT * FROM history h 
WHERE emp_nr = 1 AND valid_from <= 9131
ORDER BY valid_from DESC 
FETCH FIRST ROW ONLY;

应该返回给我员工在 2015 年 1 月 1 日分配到的组。

我需要帮助的是创建一个连接所有表的语句对整个组而不是仅对一个员工执行相同的操作(因为数据库中有数千名员工,我只想要最多 10 个组的数据)。

我很感谢任何指向正确方向的指针。

【问题讨论】:

  • 至于“我只想要最多10组的数据”:你会如何决定哪些组?仅通过where group.nr in (10,20,30,...) 或您要应用的某种算法?
  • 是的,我将只使用 WHERE 子句过滤掉我需要从中获取数据的组。

标签: sql oracle greatest-n-per-group


【解决方案1】:

使用 row_number 对您的历史记录进行排名并获取最新组,就像您对 FETCH FIRST 查询所做的那样:

select *
from
(
  select 
    h.*,
    row_number() over (partition by emp_nr order by valid_from desc) as rn
  from history h 
  where valid_from <= 9131
)
where rn = 1

然后您可以将此结果与其他表连接。

【讨论】:

  • 非常感谢您的想法。您关于使用 row_number 的评论帮助我解决了我的问题。我现在能够完成我的查询并且它按预期工作。我想我的问题是我没有很强的Oracle SQL背景,所以我不知道这个函数。
  • 我很高兴这对你有用。但是,此查询中没有特定于 Oracle 的内容;它是普通的标准 SQL(除了派生表在标准 SQL 中需要别名,而 Oracle 不需要)。值得一看像row_number 这样的分析函数(又名窗口函数)。例如,很容易得到一个运行总数(使用sum over),没有它们就很麻烦。一些 DBMS(例如 MySQL)不支持分析函数(目前),所以像这些相当简单的任务可能很难在那里解决。
  • 我的大部分 SQL 知识都来自使用 MySQL,所以我想这就是我不了解分析函数的原因。但是,嘿,感谢您指出这一点,我现在肯定会研究这个话题:)