web-dev-qa-db-fra.com

Est-il possible d'obtenir plusieurs valeurs d'une sous-requête?

Est-il possible qu'une sous-requête renvoie plusieurs colonnes dans Oracle db? (Je sais que ce SQL spécifique va provoquer une erreur, mais il résume bien ce que je veux)

select
    a.x,
    ( select b.y, b.z from b where b.v = a.v),
from a

Je veux un résultat comme celui-ci:

a.x | b.y | b.z
---------------
1   | 2   | 3

Je sais qu'il est possible de résoudre ce problème par des jointures, mais ce n'est pas ce que je demande.

Ma question est simplement s'il y a un moyen, d'obtenir deux ou plusieurs valeurs d'une sous-requête? Peut-être une solution de contournement utilisant dual? Alors qu'il n'y a PAS de jointure réelle, mais une nouvelle sous-requête pour chaque ligne?

EDIT: Ceci est une question de principe. Vous pouvez résoudre tous ces problèmes en utilisant join, je sais. Vous n'avez pas du tout besoin de sous-requêtes de ce type (pas même pour une colonne). Mais ils sont là. Alors, puis-je les utiliser de cette façon ou est-ce tout simplement impossible?

27
John Smith

Une sous-requête dans la clause Select, comme dans votre cas, est également appelée une sous-requête scalaire, ce qui signifie qu'il s'agit d'une forme d'expression. Cela signifie qu'il ne peut renvoyer qu'une seule valeur.

Je crains que vous ne puissiez pas renvoyer plusieurs colonnes d'une même sous-requête Scalar, non.

En savoir plus sur les sous-requêtes Oracle Scalar:

http://docs.Oracle.com/cd/B19306_01/server.102/b14200/expressions010.htm#i1033549

16
Henrique Ordine

C'est incorrect, mais vous pouvez essayer:

select
    a.x,
    ( select b.y from b where b.v = a.v) as by,
    ( select b.z from b where b.v = a.v) as bz
from a

vous pouvez également utiliser une sous-requête dans join

 select
        a.x,
        b.y,
        b.z
    from a
    left join (select y,z from b where ... ) b on b.v = a.v

ou 

   select
        a.x,
        b.y,
        b.z
    from a
    left join b on b.v = a.v
17
Parado

Voici deux méthodes pour obtenir plus d'une colonne dans une sous-requête scalaire (ou une sous-requête en ligne) et interroger la table de recherche une seule fois. C'est un peu compliqué mais peut être très efficace dans certains cas particuliers.

  1. Vous pouvez utiliser la concaténation pour obtenir plusieurs colonnes à la fois :

    SELECT x, 
           regexp_substr(yz, '[^^]+', 1, 1) y,
           regexp_substr(yz, '[^^]+', 1, 2) z
      FROM (SELECT a.x,
                   (SELECT b.y || '^' || b.z yz
                      FROM b
                     WHERE b.v = a.v)
                      yz
              FROM a)
    

    Vous devez vous assurer qu'aucune colonne de la liste ne contient le caractère de séparation.

  2. Vous pouvez également utiliser objets SQL :

    CREATE OR REPLACE TYPE b_obj AS OBJECT (y number, z number);
    
    SELECT x, 
           v.yz.y y,
           v.yz.z z
      FROM (SELECT a.x,
                   (SELECT b_obj(y, z) yz
                      FROM b
                     WHERE b.v = a.v)
                      yz
              FROM a) v
    
7
Vincent Malgrat

Ne pouvez-vous pas utiliser JOIN comme celui-ci?

SELECT
a.x , b.y, b.z 
FROM a 
LEFT OUTER JOIN b ON b.v = a.v

(Je ne connais pas la syntaxe Oracle. J'ai donc écrit la syntaxe SQL)

2
hims056

vous pouvez utiliser cross apply:

select
    a.x,
    bb.y,
    bb.z
from
    a
    cross apply
    (   select b.y, b.z
        from b
        where b.v = a.v
    ) bb

S'il n'y aura pas de ligne de b à mach rangée de a alors cross apply ne renverra pas de ligne. Si vous avez besoin de telles lignes, utilisez outer apply

Si vous devez rechercher une seule ligne spécifique pour chacune des lignes de a , essayez:

    cross apply
    (   select top 1 b.y, b.z
        from b
        where b.v = a.v
        order by b.order
    ) bb
2
pi.314

En requête Oracle 

select a.x
            ,(select b.y || ',' || b.z
                from   b
                where  b.v = a.v
                and    rownum = 1) as multple_columns
from   a

peut être transformé en:

select a.x, b1.y, b1.z
from   a, b b1
where  b1.rowid = (
       select b.rowid
       from   b
       where  b.v = a.v
       and    rownum = 1
)

Est utile lorsque nous voulons éviter la duplication pour la table A . De même, nous pouvons augmenter le nombre de tables:

.... where (b1.rowid,c1.rowid) = (select b.rowid,c.rowid ....
1
Rustamspl

Consultez ce site Web: http://www.w3resource.com/sql/subqueries/multiplee-row-column-subqueries.php

Exemple d'utilisation

sélectionnez ord_num, agent_code, ord_date, ord_amount
des commandes
where (agent_code, ord_amount) IN
(SELECT agent_code, MIN (ord_amount)
DE COMMANDES
GROUP BY agent_code); 

0
Antonio Santiago