powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Пересортировать строку с номерами
11 сообщений из 11, страница 1 из 1
Пересортировать строку с номерами
    #39773969
IFK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
IFK
Гость
Уважаемый форум,

Необходимо реализовать решение задачи под сиквелом:
- дано: строка вида "54-150, 151-200, 1-45, 210-300, 46-53, 201-209" и т.д.
- требуется: отсортировать значения в строке по возрастанию, т.е. вышеприведенная строка должна быть преобразована в "1-45, 46-53, 54-150, 151-200, 201-209, 210-300"

Как бы это сделать поэффективнее, без кучи курсоров и т.д.?

Спасибо!
...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39773984
Руслан Дамирович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IFK,
как-то так
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
DECLARE 
  @temp TABLE (
    [id] INT IDENTITY(1,1),
    [string] NVARCHAR(MAX),
    PRIMARY KEY ( [id] )
  )
;
INSERT
INTO
  @temp
VALUES
  ( '54-150, 151-200, 1-45, 210-300, 46-53, 201-209' ),
  ( '1-45, 46-53, 54-150, 151-200, 201-209, 210-300' )
;
WITH
tt0 AS (
  SELECT
    [id],
    [xml] = CONVERT( XML, N'<i>' + REPLACE( [string], N', ', N'</i><i>' ) + N'</i>' )
  FROM
    @temp
),
tt1 AS (
  SELECT
    tt0.[id],
    [value] = x.[v].[value]( N'.', N'NVARCHAR(255)' )
  FROM
    tt0
    CROSS APPLY tt0.[xml].[nodes]( N'i' ) x( [v] )
),
tt2 AS (
  SELECT
    tt1.[id],
    tt1.[value],
    [rn] = ROW_NUMBER() OVER ( PARTITION BY tt1.[id] ORDER BY TRY_PARSE( ss2.[value1] AS INT ), TRY_PARSE( ss2.[value2] AS INT ) )
  FROM
    tt1
    CROSS APPLY (
      SELECT
        [i] = CHARINDEX( '-', tt1.[value] )
    ) ss1
    CROSS APPLY (
      SELECT
        [value1] = CASE WHEN ss1.[i] > 1 THEN LEFT( tt1.[value], ss1.[i] - 1 ) ELSE tt1.[value] END,
        [value2] = CASE WHEN ss1.[i] > 1 THEN RIGHT( tt1.[value], LEN( tt1.[value] ) - ss1.[i] ) ELSE NULL END
    ) ss2
)
SELECT
  [id],
  [string],
  [new] = STUFF( CONVERT( VARCHAR(MAX), (
    SELECT [*] =  ', ' + [value] FROM tt2 WHERE tt2.[id] = tt0.[id] ORDER BY [rn] FOR XML PATH('') ) 
    ), 1, 2, '' )
FROM
  @temp tt0
;

...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39773987
IFK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
IFK
Гость
Руслан Дамирович, огромное спасибо!
...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39774048
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IFK,

Проще и компактнее:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
declare @t table(s varchar(max));

insert into @t
values
 ('54-150, 151-200, 1-45, 210-300, 46-53, 201-209');

select
 t.s, stuff(r.x.value('.', 'varchar(max)'), 1, 2, '')
from
 @t t cross apply
 (
  select
   ', ' + c.n1+ '-' + c.n2
  from
   (select cast('<i n1 = "' + replace(replace(t.s, '-', '" n2 = "'), ',', '"/><i n1 = "') + '"/>' as xml)) a(x) cross apply
   a.x.nodes('i') b(n) cross apply
   (
    select
     b.n.value('@n1', 'varchar(10)'),
     b.n.value('@n2', 'varchar(10)'),
     b.n.value('@n1', 'int')
   ) c(n1, n2, k)
  order by
   c.k
  for xml path(''), type
 ) r(x);
...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39774240
Руслан Дамирович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,

cool!
...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39774251
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmIFK,

Проще и компактнее:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
declare @t table(s varchar(max));

insert into @t
values
 ('54-150, 151-200, 1-45, 210-300, 46-53, 201-209');

select
 t.s, stuff(r.x.value('.', 'varchar(max)'), 1, 2, '')
from
 @t t cross apply
 (
  select
   ', ' + c.n1+ '-' + c.n2
  from
   (select cast('<i n1 = "' + replace(replace(t.s, '-', '" n2 = "'), ',', '"/><i n1 = "') + '"/>' as xml)) a(x) cross apply
   a.x.nodes('i') b(n) cross apply
   (
    select
     b.n.value('@n1', 'varchar(10)'),
     b.n.value('@n2', 'varchar(10)'),
     b.n.value('@n1', 'int')
   ) c(n1, n2, k)
  order by
   c.k
  for xml path(''), type
 ) r(x);

Чего-то это слишком просто!
...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39774271
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iapЧего-то это слишком просто!

на 16-ом/17-ом уопще "шара" :)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
DECLARE 
  @temp TABLE (
    [id] INT IDENTITY(1,1),
    [string] NVARCHAR(MAX),
    PRIMARY KEY ( [id] )
  )
;
INSERT
INTO
  @temp
VALUES
  ( '54-150, 151-200, 1-45, 210-300, 46-53, 201-209' ),
  ( '1-45, 46-53, 54-150, 151-200, 201-209, 210-300' )
;

--	**************************************************************************************
;with cte as (
	select a.id, b.value from @temp a
	cross apply (select rtrim(ltrim(value)) as value from STRING_SPLIT([string],',') t) b
)
select
	id
	,substring((select ','+b.value from cte b where a.id=b.id order by cast(replace(b.value,'-','.') as float) for xml path('')),2,100500) as xz
from @temp a


idxz11-45,46-53,54-150,151-200,201-209,210-30021-45,46-53,54-150,151-200,201-209,210-300
...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39774277
Руслан Дамирович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,
Там вообще интервалы записаны, так что можно сортировать по числу до "-".
Меня больше беспокоит, что эта задача решается post, а не ante.

P.S. Я тут вспомнил, что у меня 2016, а я все еще через XML делаю по привычке.
...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39774296
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тогда уж чисто для 2017-го :)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select
 a.string, b.string
from
 @temp a cross apply
 (
  select
   string_agg(trim(value), ', ') within group (order by try_cast(replace(value, '-', '.') as float))
  from
   string_split(a.string, ',')
 ) b(string);
...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39774697
IFK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
IFK
Гость
Пардон, забыл сообщить, что у меня 2012, так что STRING_SPLIT не прокатит. Остается вариант через xml. Всем большое спасибо - пойду разбираться, как это работает. :)
...
Рейтинг: 0 / 0
Пересортировать строку с номерами
    #39774706
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Руслан Дамировичcourt,
Там вообще интервалы записаны, так что можно сортировать по числу до "-".
Меня больше беспокоит, что эта задача решается post, а не ante.

P.S. Я тут вспомнил, что у меня 2016, а я все еще через XML делаю по привычке.
Да всё еще проще :-)))
Т.к. сортируем, фактически, по первому значению, то делаем replace '-' на '.', делаем TRY_convert в numeric, и по этому нумерику - сортируем.
:-))))
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Пересортировать строку с номерами
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]