|
Программирование >> Преобразование значений null
половиная UNION ALL) посредством рекурсии создается список. Чтобы понять, как это происходит, проанализируем некоторые фрагменты решения: сначала третий элемент списка SELECT второго запроса операции UNION ALL: x.list , e.ename и затем конструкцию WHERE того же запроса: where e.deptno = x.deptno and e.empno > x.empno Сначала в решении проверяется, что все служащие относятся к одному отделу. Затем к каждому служащему, возвращенному верхней частью операции UNION ALL, добавляются имена служащих, которым соответствуют большие значения в столбце EMPNO. Таким образом, гарантируется, что к данному служащему не будет добавлено его собственное имя. Выражение x.len+1 увеличивает LEN (изначально равное 1) на единицу при обработке каждого последующего служащего. Если это значение равно количеству служащих в отделе: where len = cnt следовательно, мы обработали данные для всех служащих и завершили создание списка. Это значение является ключевым для запроса, потому что не только сигнализирует о завершении создания списка, но также прекращает дальнейшее рекурсивное выполнение в надлежащий момент. MySQL Всю работу выполняет функция GROUP CONCAT. Она осуществляет конкатенацию значений столбца, переданного в нее, в данном случае -ENAME. Эта функция является агрегатной; таким образом, в запросе необходим оператор GROUP BY. Oracle Первый шаг к пониманию запроса Oracle - разложить его на части. Отдельно выполняя вложенный запрос (строки 4-10), формируем результирующее множество, включающее следующие данные для каждого служащего: отдел, имя, ранг в соответствующем отделе, получаемый путем сортировки по возрастанию по столбцу EMPNO, и количество служащих в отделе. Например: select deptno, ename, row number() over (partition by deptno order by empno) rn,
Назначение столбца ранга (которому в запросе присвоен псевдоним RN) - обеспечить возможность обхода дерева. Поскольку функция ROW NUMBER формирует список, начиная с единицы, без повторов или пропусков, для того чтобы обратиться к предыдущей (или родительской) строке, необходимо просто вычесть единицу (из текущего значения). Например, предыдущим числом для 3 является 3 минус 1, что равняется 2. В данном контексте, 2 - родитель 3; наблюдать это можно в строке 12. Кроме того, строки start with rn = 1 connect by prior deptno = deptno определяют корень для каждого DEPTNO как запись, в которой значение RN равно 1, и создают новый список для каждого нового отдела (при каждом обнаружении в столбце RN значения 1). Здесь важно подробнее остановиться на части ORDER BY функции ROW NUMBER. Помните, что имена ранжированы по EMPNO и список будет создаваться в соответствующем порядке. Вычисляется количество служащих в отделе (представление под псевдонимом CNT), и это значение обеспечивает, что запрос возвратит список, включающий имена всех служащих отдела. Это необходимо, потому что SYS CONNECT BY PATH создает список путем многократных итераций, и никому не нужен в итоге неполный список. Для иерархических запросов значения псевдостолбца LEVEL (уровень) начинаются с 1 (для запросов, не использующих CONNECT BY, LEVEL равен 0; для версий 10g и более поздних LEVEL доступен только в сочетании с CONNECT BY) и увеличиваются на единицу после добавления каждого служащего отдела (для каждого уровня вложенности иерархии). Поэтому, как только LEVEL становится равным CNT, мы знаем, что достигли последнего EMPNO и получим полный список. count(*) over (partition by deptno) cnt Функция SYS CONNECT BY PATH ставит выбранный разделитель (в данном случае запятую) первым элементом списка. Такое поведение может быть нежелательным. В решении данного рецепта вызов функции LTRIM удаляет запятую, стоящую в начале списка. PostgreSQL В решении PostgreSQL необходимо заранее знать максимальное число служащих в каждом отделе. Если выполнить отдельно вложенный запрос (строки 11-18), сформируется результирующее множество, включающее (для каждого служащего) отдел, имя с запятой в конце, количество служащих в отделе и количество служащих, значение EMPNO которых меньше, чем у данного служащего:
Скалярный подзапрос, POS (строки 14-15), используется для ранжирования служащих по EMPNO. Например, строка max(case when pos = 1 then ename else end) проверяет значение столбца POS на равенство 1. Выражение CASE возвращает имя служащего, если значение POS равно 1, и NULL в противном случае. Сначала надо создать запрос для определения, какое максимальное число значений может содержаться в одном списке. Исходя из таблицы EMP, наибольшее число служащих в отделе - шесть, поэтому в любом списке может быть не более шести элементов. Следующий шаг - создание списка. Это делается посредством применения некоторой условной логики (в форме выражения CASE) к строкам, возвращаемым вложенным запросом. Выражений CASE должно быть столько же, сколько существует значений, подлежащих конкатенации. Если значение POS равно 1, текущее имя добавляется в список. Второе выражение CASE оценивает, равно ли значение POS двум; если да, то
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.224
При копировании материалов приветствуются ссылки. |