оракул запрос с несколькими подзапросами - PullRequest
2 голосов
/ 17 июня 2009

попытка выбрать строки таблицы и затем использовать подзапросы для генерации списка из одной строки (item1, item2, item3)

в любом случае sql:

select 
  username,
  concat(firstname || ' ', lastname) as name,
  email,
  phone,
  (
  select 
    ltrim(sys_connect_by_path(res, ', '), ', ')
  from (
    select 
      count(*) over() as cnt, 
      row_number() over(order by ofield) as rnum, 
      (select name from rooms where code=roomcode) as res 
    from adminrooms
    where roomcode=admins.code) /*admins.code - come from main query but it gives error: invalid identifier*/
  where cnt=rnum start with rnum=1 connect by prior rnum=(rnum-1)
  ) as groups
from admins
where frozen=0 and (type <> 'root' or type is null)

проблема, кажется, в основном поле запроса 'code' из таблицы 'admins' не работает внутри запроса генерации списка

Ответы [ 4 ]

2 голосов
/ 17 июня 2009

Я могу воспроизвести ваши выводы на простом примере. Рассмотрим:

SQL> SELECT (SELECT d1.dummy FROM dual d2) d2
  2    FROM dual D1;

D2
--
X

Это работает, потому что подзапрос "d2" может видеть строки основного запроса "d1", но если мы добавим уровень, я получу ту же ошибку, что и вы:

SQL> SELECT (SELECT NULL FROM (SELECT d1.dummy FROM dual d3))
  2  FROM dual D1;

SELECT (SELECT NULL FROM (SELECT d1.dummy FROM dual d3))
FROM dual D1                     ~

ORA-00904: "D1"."DUMMY": invalid identifier

Здесь подзапрос «D3» не может видеть значения строки из «D1».

Вам нужно будет изменить ваш запрос:
* соедините admin с adminrooms, а затем используйте sys_connect_by_path или
* напишите функцию, которая примет код в качестве параметра и выведет результат вашего выбора.

Предоставьте нам CREATE TABLE и образцы данных, если вам нужен пример.

0 голосов
/ 18 июня 2009

Попробуйте переписать свой подзапрос

   (
    select 
      count(*) over() as cnt, 
      row_number() over(order by ofield) as rnum, 
      (select name from rooms where code=roomcode) as res 
    from adminrooms
    where roomcode=admins.code)

как таблица в основном запросе, как

 ... from admins, 
       (
        select 
          roomcode,
          count(*) over() as cnt, 
          row_number() over(order by ofield) as rnum, 
          (select name from rooms where code=roomcode) as res 
        from adminrooms) t
 where t.roomcode = admins.code...

И используйте wmsys.WM_CONCAT() вместо sys_connect_by_path()

0 голосов
/ 18 июня 2009

На основе вашей диаграммы БД лучший способ сделать это - использовать пользовательскую функцию агрегирование строк , а затем просто сгруппировать. Это похоже на mysql group_concat.

Если вы создаете функцию с именем string_agg (), используя вышеуказанную ссылку, вы можете использовать ее, как показано ниже в вашем коде:

select a.username, string_agg(c.name) from admins a, adminrooms b, groups c
where a.code=b.admincode
and b.groupcode=c.code
group by a.username

Вот сценарий создания функции string_agg. Просто запустите это как скрипт, и у вас будет функция выше (взято из ссылки, показанной выше):

CREATE OR REPLACE TYPE t_string_agg AS OBJECT
(
  g_string  VARCHAR2(32767),

  STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)
    RETURN NUMBER,

  MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,
                                       value  IN      VARCHAR2 )
     RETURN NUMBER,

  MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,
                                         returnValue  OUT  VARCHAR2,
                                         flags        IN   NUMBER)
    RETURN NUMBER,

  MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,
                                     ctx2  IN      t_string_agg)
    RETURN NUMBER
);
/
SHOW ERRORS


CREATE OR REPLACE TYPE BODY t_string_agg IS
  STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)
    RETURN NUMBER IS
  BEGIN
    sctx := t_string_agg(NULL);
    RETURN ODCIConst.Success;
  END;

  MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,
                                       value  IN      VARCHAR2 )
    RETURN NUMBER IS
  BEGIN
    SELF.g_string := self.g_string || ',' || value;
    RETURN ODCIConst.Success;
  END;

  MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,
                                         returnValue  OUT  VARCHAR2,
                                         flags        IN   NUMBER)
    RETURN NUMBER IS
  BEGIN
    returnValue := RTRIM(LTRIM(SELF.g_string, ','), ',');
    RETURN ODCIConst.Success;
  END;

  MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,
                                     ctx2  IN      t_string_agg)
    RETURN NUMBER IS
  BEGIN
    SELF.g_string := SELF.g_string || ',' || ctx2.g_string;
    RETURN ODCIConst.Success;
  END;
END;
/
SHOW ERRORS


CREATE OR REPLACE FUNCTION string_agg (p_input VARCHAR2)
RETURN VARCHAR2
PARALLEL_ENABLE AGGREGATE USING t_string_agg;
/
SHOW ERRORS
0 голосов
/ 17 июня 2009

Полагаю, что в таблице "admins" нет столбца "code" ... это просто маленькая ошибка. Если бы это было так, вы бы не хотели присоединяться к номеру комнаты администратора, скорее к чему-то вроде «admincode = admins.code».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...