[英]Restart of rownumber based on count in other table in oracle sql
我有两个没有公用键的表,我想在没有笛卡尔联接的情况下对这两个表进行联接。 表1大约有40,000行(每天生产的记录数各不相同),而table2当前计数为80,000行(每天生产的记录数各异)。
表1:-NAME_VALUES
NAME_VAL
--------
TOM
DICK
HARRY
表2:-CUS_TABLE
CUS_ID
---------
401795480
201134211
137643082
876450821
777290153
111035791
579865552
我想要输出以下内容
401795480 TOM
201134211 DICK
137643082 HARRY
876450821 DICK
777290153 HARRY
111035791 TOM
579865552 DICK
我的想法是为每个表分配行号。 对于表2,一旦达到表1的最大计数,我想重新启动行号,如下所示,但无法弄清楚如何执行
Table1
NAME_VAL TABLE1_RN
---------------------
TOM 1
DICK 2
HARRY 3
Table2
CUS_ID TABLE2_RN
--------------------
401795480 1
201134211 2
137643082 3
876450821 1
777290153 2
111035791 3
579865552 1
现在,我有了一把钥匙,可以轻松映射以获取所需的详细信息。
请建议是否有任何方法可以满足我的要求。
这是在连接谓词上使用取模运算符的一个很慢的解决方案:
SELECT cus_id, name_val
FROM (
SELECT cus_id, ROWNUM - 1 rn
FROM cus_table
) c
JOIN (
SELECT name_val, ROWNUM - 1 rn, MAX(ROWNUM) OVER() total
FROM name_values
) n
ON n.rn = MOD(c.rn, n.total)
ORDER BY c.rn
以上收益
CUS_ID NAME_VAL
--------------------
401795480 TOM
201134211 DICK
137643082 HARRY
876450821 TOM
777290153 DICK
111035791 HARRY
579865552 TOM
为了加快上述过程,您有几种选择,包括为c
和n
创建n.rn - 1
化视图,或在源中预先计算n.rn - 1
和MOD(c.rn - 1, n.total)
。表,同时在这些预先计算的表上放置索引。
如果允许您在系统中编写PL / SQL,则显然可以为此使用PIPELINED
函数:
CREATE TYPE rec AS OBJECT (
cus_id NUMBER(18),
name_val VARCHAR2(50)
);
/
CREATE TYPE tab AS TABLE OF rec;
/
CREATE OR REPLACE FUNCTION f RETURN tab PIPELINED AS
TYPE name_vals IS TABLE OF name_values.name_val%type;
v_name_vals name_vals;
BEGIN
SELECT name_val
BULK COLLECT INTO v_name_vals
FROM name_values;
FOR cus IN (SELECT cus_id, ROWNUM rn FROM cus_table)
LOOP
PIPE ROW(rec(cus.cus_id, v_name_vals(MOD(cus.rn - 1, v_name_vals.count) + 1)));
END LOOP;
RETURN;
END;
/
然后使用该函数,如下所示:
SELECT * FROM TABLE(f);
使用SQL Model子句,它不需要联接操作。
select cus_id, name_val
from (select cus_id,
mod(row_number() over (order by 1) - 1, (select count(*) cnt from name_values)) + 1 rn
from cus_table)
model
reference nv on (select name_val, rownum rn from name_values) dimension by (rn) measures (name_val)
main cus
dimension by (cus_id, rn)
measures (cast((null) as varchar2(4000)) as name_val)
rules upsert all
(
name_val[any, any] = nv.name_val[cv(rn)]
);
和示例执行:
SQL> WITH
2 name_values (name_val) AS (
3 SELECT 'TOM' FROM dual UNION ALL
4 SELECT 'DICK' FROM dual UNION ALL
5 SELECT 'HARRY' FROM dual
6 ),
7 cus_table (cus_id) AS (
8 SELECT 401795480 FROM dual UNION ALL
9 SELECT 201134211 FROM dual UNION ALL
10 SELECT 137643082 FROM dual UNION ALL
11 SELECT 876450821 FROM dual UNION ALL
12 SELECT 777290153 FROM dual UNION ALL
13 SELECT 111035791 FROM dual UNION ALL
14 SELECT 579865552 FROM dual
15 )
16 select cus_id, name_val
17 from (select cus_id,
18 mod(row_number() over (order by 1) - 1, (select count(*) cnt from name_values)) + 1 rn
19 from cus_table)
20 model
21 reference nv on (select name_val, rownum rn from name_values) dimension by (rn) measures (name_val)
22 main cus
23 dimension by (cus_id, rn)
24 measures (cast((null) as varchar2(4000)) as name_val)
25 rules upsert all
26 (
27 name_val[any, any] = nv.name_val[cv(rn)]
28 );
CUS_ID NAME_VAL
---------- --------------------
401795480 TOM
876450821 TOM
579865552 TOM
201134211 DICK
777290153 DICK
137643082 HARRY
111035791 HARRY
7 rows selected
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.