简体   繁体   English

根据Oracle SQL中其他表中的计数重新启动行号

[英]Restart of rownumber based on count in other table in oracle sql

i have two tables which doesn't have a common key i wanted to do a join on these two tables without a cartesian join. 我有两个没有公用键的表,我想在没有笛卡尔联接的情况下对这两个表进行联接。 Table 1 had around 40,000 ( record count varies in every day production ) rows while table2 present count is 80,000 rows ( record count varies in every day production ). 表1大约有40,000行(每天生产的记录数各不相同),而table2当前计数为80,000行(每天生产的记录数各异)。

TABLE1 :- NAME_VALUES 表1:-NAME_VALUES

NAME_VAL
--------
TOM
DICK
HARRY 

TABLE2 :- CUS_TABLE 表2:-CUS_TABLE

CUS_ID
---------
401795480  
201134211 
137643082 
876450821 
777290153 
111035791 
579865552 

I wanted to have some thing like below as output 我想要输出以下内容

401795480 TOM
201134211 DICK
137643082 HARRY
876450821 DICK
777290153 HARRY
111035791 TOM
579865552 DICK

My idea was to assign rownumber for each table . 我的想法是为每个表分配行号。 For table 2 i would like to restart the rownumber once the maximum count of table 1 is reached some thing like below but unable to figure out how can i perform 对于表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 

Now i have a key and can easily map to fetch the details i require. 现在,我有了一把钥匙,可以轻松映射以获取所需的详细信息。

Please suggest if any method can satisfy my requirement. 请建议是否有任何方法可以满足我的要求。

Canonical (possibly slow) solution showing the idea 规范(可能很慢)的解决方案表明了这一想法

Here's a rather slow solution using the modulo operator on your join predicate: 这是在连接谓词上使用取模运算符的一个很慢的解决方案:

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

The above yields 以上收益

CUS_ID      NAME_VAL
--------------------
401795480   TOM
201134211   DICK
137643082   HARRY
876450821   TOM
777290153   DICK
111035791   HARRY
579865552   TOM

SQLFiddle here SQLFiddle在这里

Faster solutions using SQL 使用SQL更快的解决方案

In order to speed up the above, you have several options, including creating materialized views for c and n , or pre-calculating the values for n.rn - 1 and MOD(c.rn - 1, n.total) in the source tables, while putting indexes on these pre-calculated tables. 为了加快上述过程,您有几种选择,包括为cn创建n.rn - 1化视图,或在源中预先计算n.rn - 1MOD(c.rn - 1, n.total) 。表,同时在这些预先计算的表上放置索引。

Faster solution using PL/SQL 使用PL / SQL更快的解决方案

If you are allowed to write PL/SQL in your system, you could obviously resort to a PIPELINED function for this: 如果允许您在系统中编写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;
/

And then use that function as follows: 然后使用该函数,如下所示:

SELECT * FROM TABLE(f);

Using SQL Model clause, which doesn't require a join operation. 使用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)]
 );

And a sample execution: 和示例执行:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM