Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Пересортировать строку с номерами / 11 сообщений из 11, страница 1 из 1
14.02.2019, 17:08
    #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
14.02.2019, 17:33
    #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
14.02.2019, 17:39
    #39773987
IFK
IFK
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересортировать строку с номерами
Руслан Дамирович, огромное спасибо!
...
Рейтинг: 0 / 0
14.02.2019, 18:57
    #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
15.02.2019, 10:01
    #39774240
Руслан Дамирович
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересортировать строку с номерами
invm,

cool!
...
Рейтинг: 0 / 0
15.02.2019, 10:12
    #39774251
iap
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
15.02.2019, 10:36
    #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
15.02.2019, 10:45
    #39774277
Руслан Дамирович
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересортировать строку с номерами
court,
Там вообще интервалы записаны, так что можно сортировать по числу до "-".
Меня больше беспокоит, что эта задача решается post, а не ante.

P.S. Я тут вспомнил, что у меня 2016, а я все еще через XML делаю по привычке.
...
Рейтинг: 0 / 0
15.02.2019, 11:06
    #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
15.02.2019, 17:20
    #39774697
IFK
IFK
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересортировать строку с номерами
Пардон, забыл сообщить, что у меня 2012, так что STRING_SPLIT не прокатит. Остается вариант через xml. Всем большое спасибо - пойду разбираться, как это работает. :)
...
Рейтинг: 0 / 0
15.02.2019, 17:28
    #39774706
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересортировать строку с номерами
Руслан Дамировичcourt,
Там вообще интервалы записаны, так что можно сортировать по числу до "-".
Меня больше беспокоит, что эта задача решается post, а не ante.

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


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