Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите сделать сортировку в рекусивном запросе.  [new]
ProBiotek
Member

Откуда: Moscow
Сообщений: 907
Привет.
Не могу придумать как сделать сортировку по уму.

Вот код:
declare @tab as Table (id int, parentid int, title nvarchar(max))

insert into @tab
values
 (1, null,'Root2'),  --<<
 (2, null,'Root1'),  --<<
 (3, 1,'aa'),
 (4, 1,'bb'),
 (5, 2,'ccc'),  --<<
 (6, 2,'aaa'),  --<<
 (7, 5,'gsd'),
 (8, 6,'wer'),
 (9, 8,'dsw'),
 (10, 9,'erer')



;with  tree (title, id, level, pathstr)
as (select title, id, 0,  CAST(id AS VARCHAR(MAX))
   from @tab tab
   where ParentId is null 
union all
   select tab.title, tab.id, level + 1, g.pathstr + '-'+CAST(tab.Id AS VARCHAR(MAX)) 
   from @tab tab
     inner join tree g on g.id = tab.ParentId) 

select *
from tree 
order by pathstr



Результат
Root2 1 0 1
aa 3 1 1-3
bb 4 1 1-4
Root1 2 0 2
ccc 5 1 2-5
gsd 7 2 2-5-7
aaa 6 1 2-6
wer 8 2 2-6-8
dsw 9 3 2-6-8-9
erer 10 4 2-6-8-9-10



Проблема в строке 'ccc' (id=5) и в строке 'aaa' (id=6). А также в Root2,Root1

Как можно переписать запрос, чтобы сортировка шла:
- по иерархии
- по алфавиту внутри одного уровня

Соответственно, чтобы сначала шла запись Root1 а не Root2. И 'aaa' была раньше 'ccc'
26 май 16, 14:48    [19223485]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
ProBiotek
Member

Откуда: Moscow
Сообщений: 907
Причем еще нужно учесть, что pathstr-строка. И если сортировать по ней, то '1-11' выйдет раньше чем '1-7'. У меня вот сейчас этот баг есть. Как исправить, чтобы сортировка по уровням была правильной ?
26 май 16, 14:53    [19223517]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
ProBiotek,

у вас пути узлов не выровнены по правому краю.
Попробуйте так:
CAST(STR(id,11) AS VARCHAR(MAX))
g.pathstr+CAST(STR(tab.id,11) AS VARCHAR(MAX))
26 май 16, 14:55    [19223526]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
iap
у вас пути узлов не выровнены по правому краю.
... и по длине строковых представлений id.
26 май 16, 14:55    [19223536]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
Konst_One
Member

Откуда:
Сообщений: 11538
для размышлений
;with  tree (title, id, level, pathstr, psort)
as 
(
select title, id, 0,  CAST(id AS VARCHAR(MAX)), RIGHT('000'+CAST(id AS VARCHAR(MAX)),3)
   from @tab tab
   where ParentId is null 
union all
   select tab.title, tab.id, level + 1, g.pathstr + '-'+CAST(tab.Id AS VARCHAR(MAX)), g.psort + '-'+RIGHT('000'+CAST(tab.Id AS VARCHAR(MAX)), 3) 
   from @tab tab
     inner join tree g on g.id = tab.ParentId
) 

select *
from tree 
order by psort
26 май 16, 15:08    [19223629]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
ProBiotek
Как можно переписать запрос, чтобы сортировка шла:
- по иерархии
- по алфавиту внутри одного уровня

Соответственно, чтобы сначала шла запись Root1 а не Root2. И 'aaa' была раньше 'ccc'

Вариант для одноцифрового id:
with  
 tb as (select row_number()over(order by title)rn, * from @tab t)
,tree as (
  select rn, title, id, 0 level,  CAST(concat(rn,'.',id) AS VARCHAR(MAX)) pathstr
    from tb where parentid is null
  union all
  select tab.rn, tab.title, tab.id, level + 1, cast(concat(g.pathstr,';',tab.rn,'.',tab.Id) AS VARCHAR(MAX)) 
    from tree g 
    join tb tab on g.id = tab.ParentId
  ) 
select *
from tree 
order by pathstr
rntitleidlevelpathstr
8Root1208.2
2aaa618.2;2.6
10wer828.2;2.6;10.8
5dsw938.2;2.6;10.8;5.9
6erer1048.2;2.6;10.8;5.9;6.10
4ccc518.2;4.5
7gsd728.2;4.5;7.7
9Root2109.1
1aa319.1;1.3
3bb419.1;3.4
26 май 16, 16:18    [19224067]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
ProBiotek
Member

Откуда: Moscow
Сообщений: 907
Спасибо всем !
26 май 16, 16:20    [19224075]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
ProBiotek
Member

Откуда: Moscow
Сообщений: 907
Konst_One,

Мне кажется этот вариант весьма интересен.
26 май 16, 16:27    [19224116]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
ProBiotek
Konst_One,

Мне кажется этот вариант весьма интересен.
STR() короче!
26 май 16, 16:28    [19224123]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
ProBiotek
Member

Откуда: Moscow
Сообщений: 907
iap,

Возможно Вы правы. я еще не со всем даже разобрался :) В любом случае погляжу все варианты - на будущее оставлю в блокнотике.
26 май 16, 16:30    [19224140]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
Konst_One
Member

Откуда:
Сообщений: 11538
iap,

я ещё не видел твоего ответа, поэтому запостил. но уж пусть ТС выбирает, что ему понятней =)
26 май 16, 16:30    [19224142]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать сортировку в рекусивном запросе.  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
ProBiotek
iap,

Возможно Вы правы. я еще не со всем даже разобрался :) В любом случае погляжу все варианты - на будущее оставлю в блокнотике.
STR() заполняет слева пробелами до указанной длины.
Максимальный int представляется десятью цифрами и возможным знаком
(понимаю при этом, что отрицательных id наверно не будет).
При этом пробел меньше любой цифры, особенно если использовать COLLATE Cyrillic_General_BIN (для верности).
26 май 16, 16:52    [19224275]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить