2016-11-12 85 views
0

我有一个列C1,C2,C3,C4,C5,C6和计数表。我必须按照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列更新为意外记录并花费比预期多得多的时间,表中有大约40万条记录。我无法在这里键入我的代码,因为实际代码在客户端计算机中。任何帮助,高度赞赏。可以使用PL/SQL或简单SQL。 DB是Oracle。

+0

为什么需要用光标和BULK COLLECT编写一个PL/SQL块并遍历每一行等?学习在普通SQL中这样做的正确方法要容易得多,而且效率要高得多 - 而且学习适当的SQL比学习PL/SQL要花费更少的时间。那么:为什么你需要在表中排序“计数”?在视图中或在查询中生成报告是有意义的;将它存放在桌子上只会导致未来的问题。如果将来某行被删除,或者C3从Y更正为X,该怎么办?现在你必须重新计算整个列!馊主意。 – mathguy

回答

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 
       ); 
+0

谢谢。使用你的查询我能够解决这个问题。 – Sid

+0

按col6排序没有韵律或理由,不知道您是否注意到。在(A,X)的情况下,OP显示按col6递减的DESC排序的“计数”,但在(A,Y)的情况下按顺序6显示ASC排序的“计数”递增。可能不值得进一步研究,因为整个任务确实没有意义。 – mathguy

0

与戈登·利诺夫提供线索的帮助下,我能解决这个问题。但是,我创建了一个新表而不是更新以避免性能问题。以下是查询:

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; 
+0

按照你所划分的那些列(或者它们的一个子集)排列的顺序会导致随机排序 - 这似乎是你想要的;在固定的c1到c5范围内,你所提供的顺序没有明显的逻辑。 (你在那里的顺序是“random”的原因是它在每个分区中,其中c1到c5对于分区中的所有行是固定的。)通过省略“order by c1”得到完全相同的(随机)结果,...,c5“全部来自row_number()参数。只需保留一部分分区。 – mathguy