Je voudrais obtenir tous les enregistrements de la première table et seulement x enregistrements de la seconde table.
Combien d'enregistrements de la deuxième table j'ai des informations dans la première table:

Mes tables sont

Tableau 1 :

WITH table1(a,b) AS
(
 SELECT 'aa',3 FROM dual UNION ALL
 SELECT 'bb',2 FROM dual UNION ALL
 SELECT 'cc',4 FROM dual
)
SELECT *
  FROM table1;
a  | b (number of records from table2 (x))
------
aa | 3
bb | 2
cc | 4

Tableau 2 :

WITH table2(a,b) AS
(
 SELECT 'aa','1xx' FROM dual UNION ALL
 SELECT 'aa','2yy' FROM dual UNION ALL
 SELECT 'aa','3ww' FROM dual UNION ALL  
 SELECT 'aa','4zz' FROM dual UNION ALL 
 SELECT 'aa','5qq' FROM dual UNION ALL 
 SELECT 'bb','1aa' FROM dual UNION ALL 
 SELECT 'bb','2bb' FROM dual UNION ALL 
 SELECT 'bb','3cc' FROM dual UNION ALL  
 SELECT 'cc','1oo' FROM dual UNION ALL 
 SELECT 'cc','2uu' FROM dual UNION ALL 
 SELECT 'cc','3tt' FROM dual UNION ALL 
 SELECT 'cc','4zz' FROM dual UNION ALL 
 SELECT 'cc','5rr' FROM dual
)
SELECT *
  FROM table2;
a  | b 
--------
aa | 1xx 
aa | 2yy 
aa | 3ww 
aa | 4zz 
aa | 5qq
bb | 1aa
bb | 2bb
bb | 3cc
bb | 4dd
bb | 5ee
cc | 1oo
cc | 2uu
cc | 3tt
cc | 4zz
cc | 5rr 

Résultat attendu:

a  | b 
--------
aa | 1xx
aa | 2yy
aa | 3ww
bb | 1aa
bb | 2bb
cc | 1oo
cc | 2uu
cc | 3tt
cc | 4zz
0
Bhau 17 sept. 2020 à 09:47

3 réponses

Meilleure réponse

Vous pouvez utiliser la fonction ROW_NUMBER() analytique avec LEFT/RIGHT OUTER JOIN parmi les tables:

WITH t2 AS
(
SELECT t2.a,t2.b, ROW_NUMBER() OVER (PARTITION BY t2.a ORDER BY t2.b) AS rn
  FROM table2 t2
)
SELECT t2.a, t2.b
  FROM t2  
  LEFT JOIN table1 t1
    ON t1.a = t2.a  
 WHERE rn <= t1.b

Démo

1
Barbaros Özhan 17 sept. 2020 à 07:41

Idéalement, vous devriez avoir une colonne de classement dans table2. Lorsque vous dites les X premières lignes, cela n'a aucun sens à moins que vous n'ayez quelque chose comme un champ d'identifiant ou de date pour classer les enregistrements.

Quoi qu'il en soit, en supposant que la partie numérique de la colonne b dans le tableau 2 pour l'ordre et en supposant que le nombre serait suivi de 2 caractères uniquement tels que xx, yy, etc., vous pouvez utiliser la logique ci-dessous

Select Tb1.a, Tb1.b
from
(Select t.*, row_number() over (partition by a order by substr(b,1,length(b)-2)) as seq
 from Table2 t) Tb1
 join Table1 Tb2
on Tb1.a = Tb2.a
Where Tb1.seq <= Tb2.b;

Démo - https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=3030b2372bcbb007606bbb6481af9884" rel="nofollow noreferrer"> https://dbfiddle.uk/?rdbms=oracle_11.2/2360b30b30b30960b30b >

0
Somy 17 sept. 2020 à 08:01

Encore une fois, c'est juste un travail pour latéral:

WITH prep AS 
( 
       SELECT * 
       FROM   tab1, 
              LATERAL 
              ( 
                     SELECT LEVEL AS lvl
                     FROM   dual 
                     CONNECT BY LEVEL <= b 
              ) 
) 
SELECT   p.a, t2.b
FROM     prep p 
JOIN     tab2 t2 
ON       p.lvl = regexp_substr(t2.b,'^\d+')
AND      p.a = t2.a 
ORDER BY p.a, p.lvl

enter image description here

0
Ranagal 17 sept. 2020 à 08:01