2015-08-14 3 views
3

Я конвертирую некоторый код Oracle в SQL Server.Сортировка нескольких родительских/дочерних элементов в рекурсивном запросе SQL

код Oracle выглядит следующим образом:

SELECT FLEX_VALUE, DESCRIPTION, ADMIN_ENABLED, PARENT_FLEX_VALUE, DISPLAY_DESC, LEVEL 
FROM ( SELECT FLEX_VALUE, DESCRIPTION, ADMIN_ENABLED, PARENT_FLEX_VALUE, vDescField AS DISPLAY_DESC 
     FROM GL_SEGMENT2 
     WHERE PERIOD_YEAR = 2015;) 
CONNECT BY PRIOR FLEX_VALUE = PARENT_FLEX_VALUE 
START WITH PARENT_FLEX_VALUE IS NULL 
ORDER SIBLINGS BY DISPLAY_DESC; 

И он производит следующие корректные результаты: Oracle Query Results (sample)

группирует запроса данных их родителей, а также уровни обозначены. Результаты упорядочиваются родительскими группами. «Дети» под заголовками групп, похоже, не заказываются. Данные хранятся в одной таблице.

Я преобразовал запрос Oracle в следующем запросе SQL Server:

WITH n ([FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [DISPLAY_DESC], [LEVEL]) AS 
    (SELECT P1.[FLEX_VALUE], P1.[DESCRIPTION], P1.[ADMIN_ENABLED], P1.[PARENT_FLEX_VALUE], P1.[DISPLAY_DESC], 1 AS [LEVEL] 
    FROM (SELECT [FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [FLEX_VALUE] + ' - ' + [DESCRIPTION] AS [DISPLAY_DESC] 
      FROM dbo.FIN_REP_GL_SEGMENT2 
      WHERE [PERIOD_YEAR] = 2015) AS P1 
    WHERE LEN(LTRIM(RTRIM(ISNULL(P1.[PARENT_FLEX_VALUE],'')))) = 0 

    UNION ALL 

    SELECT C1.[FLEX_VALUE], C1.[DESCRIPTION], C1.[ADMIN_ENABLED], C1.[PARENT_FLEX_VALUE], C1.[DISPLAY_DESC], Parent.[LEVEL] + 1 
    FROM (SELECT [FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [FLEX_VALUE] + ' - ' + [DESCRIPTION] AS [DISPLAY_DESC] 
      FROM dbo.FIN_REP_GL_SEGMENT2 
      WHERE [PERIOD_YEAR] = 2015) AS C1 

    JOIN n Parent ON Parent.[FLEX_VALUE] = C1.[PARENT_FLEX_VALUE]) 

SELECT [FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [DISPLAY_DESC], [LEVEL] 
FROM n 
ORDER BY [DISPLAY_DESC] 

Этот запрос SQL-сервер производит некорректной сортировкой, как показано ниже:

Bad SQL Query

Уровни кажутся правильно, но дети отображаются под неправильными родительскими категориями (обратите внимание на значения B145 и Cnnn). Запись B145 должна отображаться под родителем F000, а записи Cnnn должны отображаться под родителем L000. В настоящее время SQL Query помещает их под родителем B000, что неверно!

SQL-запрос, похоже, сортируется по столбцу FLEX_VALUE, независимо от того, к какому «родительскому» принадлежит «ребенок».

Первопричина [так в оригинале] вопрос, кажется, что есть НЕСКОЛЬКО корневые записи с NULL в их PARENT_FLEX_VALUE, и я на самом деле хочу, чтобы игнорировать буквенную сортировку по FLEX_VALUE (я только обеспокоен с РОДИТЕЛЬСКИЙ СОРТИРОВОЧНЫЙ ЗАКАЗ).

Все, что я пытаюсь выполнить с SQL-запросом, не изменяет порядок сортировки.

Помимо проблемы сортировки и группировки, запрос в основном работает.

Повторно обработанный пример моей текущей попытки запроса SQL Server с объяснением причин, по которым он в настоящее время не работает, будет очень оценен.

+1

Не проблема, что у вас есть заказ DISPLAY_DESC? –

+0

№. DISPALY_DESC просто согласовывает FLEX_VALUE с ОПИСАНИЕМ. Уже пробовали сортировку по FLEX_VALUE и PARENT_FLEX_VALUE. Нет эффекта. Сортировка по PARENT_FLEX просто помещает всех родителей в верхнюю часть списка. Он не показывает иерархию - это то, что я хочу. – user1058946

+1

Я бы предположил, что заказ должен быть «PARENT_FLEX_VALUE, CASE WHEN LEVEL = 1 THEN 1 ELSE 0 END, DISPLAY_DESC' – MickyT

ответ

2

Этот запрос Oracle, похожий на ваш, рекурсивный, должен помочь. Я думаю, что вы можете легко изменить его до версии SQL Server:

with t(FV, DSC, PFV, path, lvl) as (
    select FLEX_VALUE, DESCRIPTION, PARENT_FLEX_VALUE, flex_value, 1 
    from gl_segment2 where parent_flex_value is null 
    union all 
    select g.FLEX_VALUE, g.DESCRIPTION, g.PARENT_FLEX_VALUE, 
     t.path||'/'||g.flex_value, t.lvl+1 
    from gl_segment2 g join t on g.parent_flex_value = t.fv) 
select t.*, lpad(' ', (lvl-1)*2, ' ')||fv hierarchy from t order by path 

Для того, чтобы сохранить иерархию я добавил path колонки, которая позволяет правильно упорядоченность. Конечно, вам не нужны столбцы PATH, LVL, HIERARCHY на выходе, я добавил их только для презентационных марионеток.

выход и SQLFiddle:

FV DSC     PFV PATH      LVL HIERARCHY 
----- -------------------- ----- ----------------- ---------- ---------- 
A000 DESCRIPTION A000   A000      1 A000 
A010 DESCRIPTION A010  A000 A000/A010     2 A010 
A100 DESCRIPTION A100  A010 A000/A010/A100    3  A100 
A101 DESCRIPTION A101  A010 A000/A010/A101    3  A101 
A011 DESCRIPTION A011  A000 A000/A011     2 A011 
B000 DESCRIPTION B000   B000      1 B000 
B010 DESCRIPTION B010  B000 B000/B010     2 B010 
B011 DESCRIPTION B011  B000 B000/B011     2 B011 
F000 DESCRIPTION F000   F000      1 F000 
B145 DESCRIPTION B145  F000 F000/B145     2 B145 
+0

Спасибо. Это работает! Было немного проблем с литьем типов данных между якорной и рекурсивной частью, но она работает хорошо. – user1058946

+0

Рабочий код: 'н (Ф.В., [по убыванию], ADMN, PFV, DISP, Ls, РТН) КАК \t (SELECT P1.FV, P1 [по убыванию], P1.ADMN, P1.PFV. , P1.DISP, 1, CAST (P1.FV AS VARCHAR (8000)) \t ОТ (SELECT FV, [DESC], ADMN, PFV, FV + '-' + [по убыванию] DISP \t \t ОТ GL_SEG2 \t \t Где PYEAR = 2015) Р1 \t ГДЕ LEN (LTRIM (RTRIM (ISNULL (P1.PFV, '')))) = 0 \t UNION ALL \t ВЫБОР C1.FV, С1. [по убыванию], C1.ADMN, C1.PFV, C1.DISP, n.LVL + 1, CAST (CONCAT (n.PTH, '/', C1.FV) AS VARCHAR (8000)) \t ОТ (SELECT FV, [DESC], ADMN, PFV, FV + '-' + [по убыванию] DISP \t \t ОТ GL_SEG2 \t \t ГДЕ PYEAR = 2015) C1- \t РЕГИСТРИРУЙТЕСЬ п на C1.PFV = n.FV) SELECT FV, [DESC], ADMN, PFV, DISP, LVL ОТ n ORDER BY n.PTH' – user1058946