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 ).
TABLE1 :- NAME_VALUES
NAME_VAL
--------
TOM
DICK
HARRY
TABLE2 :- 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
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.
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
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.
If you are allowed to write PL/SQL in your system, you could obviously resort to a PIPELINED
function for this:
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.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.