根据oracle sql中其他表中的count重新启动rownumber

时间:2016-01-10 11:25:39

标签: sql oracle

我有两个没有公共密钥的表我想在没有笛卡尔联接的情况下在这两个表上进行连接。 表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

我的想法是为每个表分配rownumber。对于表2,我希望在达到表1的最大计数后重新启动rownumber,如下所示,但无法弄清楚如何执行

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 

现在我有了一个密钥,可以轻松映射以获取我需要的详细信息。

请建议任何方法是否符合我的要求。

2 个答案:

答案 0 :(得分:4)

显示想法

的典型(可能很慢)解决方案

这是使用连接谓词上的模运算符的一个相当慢的解决方案:

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

SQLFiddle here

使用SQL

的更快解决方案

为了加快上述速度,您有多种选择,包括为cn创建实体化视图,或预先计算n.rn - 1和{{1}的值在源表中,将索引放在这些预先计算的表上。

使用PL / SQL

加快解决方案

如果允许您在系统中编写PL / SQL,显然可以使用MOD(c.rn - 1, n.total)函数:

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;
/

答案 1 :(得分:0)

使用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