Подтвердить что ты не робот

Можно ли получить несколько значений из подзапроса?

Есть ли способ, чтобы подзапрос возвращал несколько столбцов в oracle db? (Я знаю, что этот конкретный sql приведет к ошибке, но он подводит итог тому, что я хочу очень хорошо)

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

Я хочу получить такой результат:

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

Я знаю, что можно решить эту проблему через объединения, но это не то, о чем я прошу.

Мой вопрос просто, если есть какой-либо способ, чтобы получить два или более значений из подзапроса? Может быть, обходной путь с использованием двойного? Так что нет никакого фактического соединения, но новый подзапрос для каждой строки?

РЕДАКТИРОВАТЬ: Это принципиальный вопрос. Я знаю, вы можете решить все эти проблемы, используя соединение. Вам вообще не нужны подзапросы (даже для одного столбца). Но они есть. Могу ли я использовать их таким образом или это просто невозможно?

4b9b3361

Ответ 1

Подзапрос в предложении Select, как и в вашем случае, также известен как Scalar Subquery, что означает, что это форма выражения. Это означает, что он может вернуть только одно значение.

Я боюсь, вы не сможете вернуть несколько столбцов из одного Скалярного подзапроса, нет.

Подробнее о Oracle Scalar Subqueries:

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

Ответ 2

Это неверно, но вы можете попробовать это вместо этого:

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

Вы также можете использовать подзапрос в соединении

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

или же

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

Ответ 3

Вот два метода, чтобы получить более одного столбца в скалярном подзапросе (или встроенном подзапросе) и запросить таблицу поиска только один раз. Это немного запутанно, но может быть очень эффективным в некоторых особых случаях.

  • Вы можете использовать конкатенацию, чтобы получить несколько столбцов одновременно:

    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)
    

    Вам нужно убедиться, что ни один столбец в списке не содержит символ разделителя.

  • Вы также можете использовать объекты 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
    

Ответ 4

Вы не можете использовать JOIN, как этот?

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

(я не знаю синтаксиса Oracle. Поэтому я написал синтаксис SQL)

Ответ 5

В запросе Oracle

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

можно преобразовать в:

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
)

Полезно, когда мы хотим предотвратить дублирование для таблицы A. Аналогично, мы можем увеличить количество таблиц:

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

Ответ 6

вы можете использовать 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

Если строка b не будет содержать строку a, тогда cross apply не будет возвращать строку. Если вам нужны такие строки, используйте outer apply

Если вам нужно найти только одну конкретную строку для каждой строки из a, попробуйте:

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