只要新值与当前值不同,Oracle SQL 将字段的值更改为列表中的其他值?

Posted

技术标签:

【中文标题】只要新值与当前值不同,Oracle SQL 将字段的值更改为列表中的其他值?【英文标题】:Oracle SQL change value of field to other value from list as long as new value different from current? 【发布时间】:2014-04-28 15:52:58 【问题描述】:

我的 Oracle 10g XE 中有一个包含 33 条员工记录的测试表。示例如下(我只展示了 5 个):

我不是 SQL 人,所以我只知道那些基本的 INSERT、UPDATE 等。我想要实现的是将每个员工的部门从另一个员工更改为另一个部门,只要它与他们当前的不同部。基本上我的想法是:

    从每个员工那里获取所有部门(DEPT A、DEPT B、DEPT B、DEPT C、DEPT A),也许将其存储在一个变量中? 对于每个员工,从之前收集的部门列表中将不同的部门放入其记录中。新部门不得与之前的记录相同。 上述示例的结果如下所示。

为了记录,不只是 DEPT A - C。我的 33 条员工记录大多具有唯一的部门。只有 2 - 3 个部门下有超过 1 名员工。因此,我可以保证,可能不会有员工记录无法分配到与其当前拥有的不同部门下的任何情况。

【问题讨论】:

【参考方案1】:

这是一个比你想象的更难的问题。首先,这是一个排列问题,因为您希望部门的最终计数相同。其次,有时无法解决(例如,如果超过一半的员工在同一部门)。

如果你想为员工改组部门,这里有一个方法:

with cte as (
      select e.*,
             row_number() over (order by emp_id) as orig_seqnum,
             row_number() over (order by dbms_random.value) as new_seqnum
      from employees e
     )
select e1.*, e2.dept as new_dept
from cte e1 join
     cte e2
     on e1.orig_seqnum = e2.new_seqnum;

保证新部门与旧部门不同。实际上有很多方法可以做到这一点。但是,鉴于您的大多数部门只有一名员工,这可能会解决您的问题。

【讨论】:

你说得对,一半以上的员工都在同一个部门,但这并不影响我的情况。无论如何,当我运行上述代码时,我得到 ORA-00904: "E": invalid identifier。什么是cte?是表名还是什么? new_dept 呢?我需要在我的表中创建一个字段 new_dept 吗?最后是 e1.seqnm。之前的代码中没有seqnm。只有 orig_seqnum 和 new_seqnum。很抱歉提出 n00bish 问题,但我真的不知道在哪里查找错误。 CTE 是with 表达式。我修复了语法错误。这是一个select 查询。如果需要更新,可以转为更新或合并。 谢谢。在我将 e1.seqnum 更改为 e1.orig_seqnum 后,它与上面的编辑代码一起工作。我会认为自己在 UPDATE 部分。顺便说一句,确实有时新部门与旧部门相同。我想这个问题最好使用适当的应用程序代码而不是 SQL 来解决。无论如何,您的解决方案现在就足够了。我只需要将我的情况改为“并非每个员工都更换部门”,因为在实际情况中就是这样。

以上是关于只要新值与当前值不同,Oracle SQL 将字段的值更改为列表中的其他值?的主要内容,如果未能解决你的问题,请参考以下文章

如果在更新触发之前未在 oracle 中进行更新,则新值与旧值相同

SQL 空值

Postgresql on conflict do update 设置当前值,原始值,当前值与原始值相加值

什么是CAS?

CakePHP 3自定义验证:如何在编辑期间将新值与旧值进行比较?

mysql的空值与NULL的区别