【问题标题】:Updating column based on previous record根据以前的记录更新列
【发布时间】:2016-11-12 13:56:43
【问题描述】:

我有一个包含 C1、C2、C3、C4、C5、C6 和 Count 列的表格。我必须使用按 C1、C2、C3、C4、C5 的顺序对记录进行排序。对于第一条记录,计数将为 0,如果下一行的 C1、C2、C3、C4、C5 的值与前一行相同,那么我必须通过添加 +1 来更新计数列。所以这就是我所期待的: 表:

C1   C2    C3    C4    C5    C6     Count
-------------------------------------------
1    A     X     X1    AA    123     0
1    A     X     X1    AA    121     1
1    A     X     X1    AA    118     2
1    A     X     X1    AA    117     3
2    B     X     X2    AA    234     0
8    A     Y     X3    AA    298     0
8    A     Y     X3    AA    800     1

我正在使用 Oracle 数据库。我用 Cursor with Order by 编写了一个 PL SQL 块,然后在 BULK COLLECT 中使用游标,并与前一条记录相比,遍历每条记录。但是,Count 列使用意外记录进行更新,并且花费的时间比预期的要多得多,表有大约 400k 条记录。我无法在此处输入我的代码,因为实际代码在客户端机器中。非常感谢任何帮助。可以使用 PL/SQL 或 Simple SQL。 DB 是 Oracle。

【问题讨论】:

  • 为什么需要用 cursor 和 BULK COLLECT 编写一个 PL/SQL 块并遍历每一行等?学习用普通 SQL 执行此操作的正确方法要容易得多,效率要高得多 - 学习正确的 SQL 所需的时间远少于学习 PL/SQL 所需的时间。然后:为什么你需要在表中的排序“计数”?在视图或查询中生成报告是有意义的;将其存储在表中只会导致将来出现问题。如果将来删除一行,或者将 C3 从 Y 更正为 X,该怎么办?现在您必须重新计算整个列!坏主意。

标签: sql oracle


【解决方案1】:

相信你想要row_number():

select t.*,
       (row_number() over (partition by c1, c2, c3, c4, c5 order by c6) - 1
       ) as "Count"
from t;

您可以使用merge 将其放入update 语句中。或者,如果你真的想要update

update t
    set count = (select count(*)
                 from t t2
                 where t2.col1 = t.col1 and t2.col2 = t.col2 and t2.col3 = t.col3 and
                       t2.col4 = t.col4 and t.col5 = t2.col5 and
                       t2.col6 < t.col6
                );

【讨论】:

  • 谢谢。使用您的查询,我能够解决问题。
  • col6 的订购没有韵律或理由,不确定您是否注意到。 OP 显示在 (A, X) 的情况下按 col6 排序的 DESC 的“计数”增加,但在 (A, Y) 的情况下按 col 6 的 ASC 排序。不过可能不值得进一步研究,因为整个作业真的没有意义。
【解决方案2】:

在 Gordon Linoff 提供的提示的帮助下,我能够解决这个问题。但是,我创建了一个新表而不是更新以避免性能问题。以下是查询:

CREATE TABLE TAB2 AS
SELECT T1.C1, T1.C2, T1.C3, T1.C4, T1.C5, T1.C6, T1.REC_COUNT 
(select t.*,
       (row_number() over (partition by c1, c2, c3, c4, c5 order by c1, c2, c3, c4, c5) - 1
       ) as rec_count
from tab1 T) T1;

【讨论】:

  • 按与您分区的列(或它们的子集)相同的列进行排序会导致随机排序 - 无论如何这似乎是您想要的;在固定的 c1 到 c5 中,您提出的顺序没有明显的逻辑。 (你有“随机”的顺序的原因是它在每个分区内,其中 c1 到 c5 对于分区中的所有行都是固定的。)通过省略“order by c1”,您会得到完全相同的(随机)结果, ..., c5" 完全来自 row_number() 参数。只保留部分分区。
猜你喜欢
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 2020-07-07
  • 2020-12-12
  • 1970-01-01
  • 2018-08-12
  • 2011-12-09
  • 2019-02-02
相关资源
最近更新 更多