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

Откуда: Симферополь
Сообщений: 540
Есть текстовая строка:
[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]
как распарсить строку (выделить документы) и получить следующий столбец записей (но номер D может быть от одного до 4 символов)

В результате должен быть следующий набор:
D123
D127
D129
27 апр 12, 12:43    [12479107]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
мимо
Guest
declare @x as varchar (250) = '[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]'

declare @xml as xml = replace(replace(REPLACE(@x,'[','<b>'),']','</b>'),' + ','')

select distinct left(y.value('.','varchar(100)'),4)
from @xml.nodes('b') as x(y)
order by 1
27 апр 12, 12:59    [12479217]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6727
Причём тут SQL, это что нельзя на клиенте делать?
27 апр 12, 13:04    [12479255]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Andrew_vb1110
Member

Откуда: Симферополь
Сообщений: 540
мимо,

спасибо конечно. А как то классическим SQL запросом, без использования XML можно сделать?
27 апр 12, 13:04    [12479256]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Мистер Хенки
Member

Откуда: канализация
Сообщений: 6615
Andrew_vb1110
мимо,

спасибо конечно. А как то классическим SQL запросом, без использования XML можно сделать?

можно через таблицу с числами, через инлайн функцию или через XML.
27 апр 12, 13:14    [12479369]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6727
Andrew_vb1110
А как то классическим SQL запросом, без использования XML можно сделать?
Это уже не класически. Забудьте. Или вам через CTE?


А мой пост вы игнорируете. Это нормально.
27 апр 12, 13:14    [12479376]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
мимо
Guest
Andrew_vb1110
мимо,

спасибо конечно. А как то классическим SQL запросом, без использования XML можно сделать?

sql - это язык. а хмл - это такой тип данных (как инт или варчар). от sql2005 и выше.
А сделать можно, конечно... А использование анпивота относится к классический скл или нет?
27 апр 12, 13:15    [12479382]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Andrew_vb1110
Member

Откуда: Симферополь
Сообщений: 540
мимо
Andrew_vb1110
мимо,

спасибо конечно. А как то классическим SQL запросом, без использования XML можно сделать?

sql - это язык. а хмл - это такой тип данных (как инт или варчар). от sql2005 и выше.
А сделать можно, конечно... А использование анпивота относится к классический скл или нет?

Да, приведите пожалуйста пример с использованием PIVOT
27 апр 12, 13:40    [12479599]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Andrew_vb1110
Member

Откуда: Симферополь
Сообщений: 540
мимо
declare @x as varchar (250) = '[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]'

declare @xml as xml = replace(replace(REPLACE(@x,'[','<b>'),']','</b>'),' + ','')

select distinct left(y.value('.','varchar(100)'),4)
from @xml.nodes('b') as x(y)
order by 1


Скрипт не работает
27 апр 12, 13:43    [12479606]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Strangers
Member [заблокирован]

Откуда: Україна
Сообщений: 2613
а так по классически? :)
SELECT distinct SUBSTRING(_Str, CHARINDEX('D',_Str,Pos-5),Pos-CHARINDEX('D',_Str,Pos-5))
FROM (SELECT @x as _Str) m
	CROSS JOIN
		(SELECT a.Pos
		FROM
			(-- первая 1000 чисел
			select k.number*100 + k1.number*10 + k2.number Pos
			from master.dbo.spt_values k
				FULL JOIN master.dbo.spt_values k1 ON k1.type = k.type and k1.number between 0 and 9
				FULL JOIN master.dbo.spt_values k2 ON k1.type = k2.type and k2.number between 0 and 9
			where k.type = 'P' and k.number between 0 and 9) a
		WHERE a.Pos between 1 and LEN(@x)
			and SUBSTRING(@x,a.Pos,1) = 'x') z 
27 апр 12, 13:44    [12479613]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Andrew_vb1110
Member

Откуда: Симферополь
Сообщений: 540
Strangers,

Ух Ты! Вот это здорово и то что мне надо. Спасибо огромное.
27 апр 12, 13:46    [12479632]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
iap
Member

Откуда: Москва
Сообщений: 47198
C помощью таблицы чисел:
DECLARE @S VARCHAR(100)='[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]';
SELECT DISTINCT SUBSTRING(@S,number+1,CHARINDEX('x',@S,number+1)-number-1)
FROM master.dbo.spt_values
WHERE type='P' AND SUBSTRING(@S,number,1)='['
ORDER BY 1;
27 апр 12, 13:49    [12479656]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
iap
Member

Откуда: Москва
Сообщений: 47198
iap
C помощью таблицы чисел:
DECLARE @S VARCHAR(100)='[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]';
SELECT DISTINCT SUBSTRING(@S,number+1,CHARINDEX('x',@S,number+1)-number-1)
FROM master.dbo.spt_values
WHERE type='P' AND SUBSTRING(@S,number,1)='['
ORDER BY 1;
Так точнее:
DECLARE @S VARCHAR(100)='[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]';
SELECT DISTINCT SUBSTRING(@S,number+1,CHARINDEX('x',@S,number+1)-number-1)
FROM master.dbo.spt_values
WHERE type='P' AND number BETWEEN 1 AND LEN(@S) AND SUBSTRING(@S,number,1)='['
ORDER BY 1;
27 апр 12, 13:52    [12479675]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Andrew_vb1110
Member

Откуда: Симферополь
Сообщений: 540
iap
iap
C помощью таблицы чисел:
DECLARE @S VARCHAR(100)='[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]';
SELECT DISTINCT SUBSTRING(@S,number+1,CHARINDEX('x',@S,number+1)-number-1)
FROM master.dbo.spt_values
WHERE type='P' AND SUBSTRING(@S,number,1)='['
ORDER BY 1;
Так точнее:
DECLARE @S VARCHAR(100)='[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]';
SELECT DISTINCT SUBSTRING(@S,number+1,CHARINDEX('x',@S,number+1)-number-1)
FROM master.dbo.spt_values
WHERE type='P' AND number BETWEEN 1 AND LEN(@S) AND SUBSTRING(@S,number,1)='['
ORDER BY 1;


У меня на самом деле переменная @S - это поле в таблице (поле Text).
ID Text
126 [D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]
Поля таблицы: ID - integer, Text - varchar(250). Мне надо перебрать по всей таблице (по полю Text).
Как лучше сделать курсор перебора по всем записям таблицы.
Т.е. окончательный рекордсет должен быть:
ID Text
126 D123
126 D127
126 D129
126 D129
126 D129
126 D129
126 D129
27 апр 12, 15:30    [12480502]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Strangers
Member [заблокирован]

Откуда: Україна
Сообщений: 2613
DECLARE @t table (ID int, [Text] varchar(250))

INSERT INTO @t 
SELECT 126, '[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]'
UNION
SELECT 127, '[D129x3y8] + [D127x3y9] + [D129x3y11] + [D129x3y12]'

SELECT DISTINCT ID, SUBSTRING([Text],number+1,CHARINDEX('x',[Text],number+1)-number-1)
FROM master.dbo.spt_values
	CROSS JOIN @t 
WHERE type='P' AND number BETWEEN 1 AND LEN([Text]) AND SUBSTRING([Text],number,1)='['
ORDER BY 1;		
27 апр 12, 15:54    [12480683]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
iap
Member

Откуда: Москва
Сообщений: 47198
Andrew_vb1110
iap
пропущено...
Так точнее:
DECLARE @S VARCHAR(100)='[D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]';
SELECT DISTINCT SUBSTRING(@S,number+1,CHARINDEX('x',@S,number+1)-number-1)
FROM master.dbo.spt_values
WHERE type='P' AND number BETWEEN 1 AND LEN(@S) AND SUBSTRING(@S,number,1)='['
ORDER BY 1;


У меня на самом деле переменная @S - это поле в таблице (поле Text).
ID Text
126 [D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]
Поля таблицы: ID - integer, Text - varchar(250). Мне надо перебрать по всей таблице (по полю Text).
Как лучше сделать курсор перебора по всем записям таблицы.
Т.е. окончательный рекордсет должен быть:
ID Text
126 D123
126 D127
126 D129
126 D129
126 D129
126 D129
126 D129
1. Создать у себя в базе данных таблицу последовательных натуральных чисел.
Пары миллионов записей должно хватить. Использовать там, где у меня master.dbo.spt_values.
2. Трудно обобщить на поля таблицы?
SELECT DISTINCT T.ID, SUBSTRING(T.[Text],V.number+1,CHARINDEX('x',T.[Text],V.number+1)-V.number-1)[Text]
FROM [Table] T
JOIN master.dbo.spt_values V
  ON V.type='P' AND V.number BETWEEN 1 AND LEN(T.[Text]) AND SUBSTRING(T.[Text],V.number,1)='['
ORDER BY 1,2;
27 апр 12, 16:02    [12480781]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6727
Столько гемора ради парсирования строк на стороне сервера.

Один раз привести данные в реляционный стандартный формат и забыть как страшный сон.
А так генерить-парсить туда-сюда по 100 раз за раз.

Зачем?
Ответ: человек любит приключения на свою *опу.
27 апр 12, 22:49    [12482528]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Andrew_vb1110
Member

Откуда: Симферополь
Сообщений: 540
iap
Andrew_vb1110
пропущено...


У меня на самом деле переменная @S - это поле в таблице (поле Text).
ID Text
126 [D129x3y8] + [D127x3y9] + [D123x3y10] + [D129x3y11] + [D129x3y12] + [D129x3y13] + [D129x3y7]
Поля таблицы: ID - integer, Text - varchar(250). Мне надо перебрать по всей таблице (по полю Text).
Как лучше сделать курсор перебора по всем записям таблицы.
Т.е. окончательный рекордсет должен быть:
ID Text
126 D123
126 D127
126 D129
126 D129
126 D129
126 D129
126 D129
1. Создать у себя в базе данных таблицу последовательных натуральных чисел.
Пары миллионов записей должно хватить. Использовать там, где у меня master.dbo.spt_values.
2. Трудно обобщить на поля таблицы?
SELECT DISTINCT T.ID, SUBSTRING(T.[Text],V.number+1,CHARINDEX('x',T.[Text],V.number+1)-V.number-1)[Text]
FROM [Table] T
JOIN master.dbo.spt_values V
  ON V.type='P' AND V.number BETWEEN 1 AND LEN(T.[Text]) AND SUBSTRING(T.[Text],V.number,1)='['
ORDER BY 1,2;


Спасибо - работает. Но я так понимаю, что ограничение идет на spt_values на 2048
28 апр 12, 09:16    [12483486]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
iap
Member

Откуда: Москва
Сообщений: 47198
Andrew_vb1110
iap
пропущено...
1. Создать у себя в базе данных таблицу последовательных натуральных чисел.
Пары миллионов записей должно хватить. Использовать там, где у меня master.dbo.spt_values.
2. Трудно обобщить на поля таблицы?
SELECT DISTINCT T.ID, SUBSTRING(T.[Text],V.number+1,CHARINDEX('x',T.[Text],V.number+1)-V.number-1)[Text]
FROM [Table] T
JOIN master.dbo.spt_values V
  ON V.type='P' AND V.number BETWEEN 1 AND LEN(T.[Text]) AND SUBSTRING(T.[Text],V.number,1)='['
ORDER BY 1,2;


Спасибо - работает. Но я так понимаю, что ограничение идет на spt_values на 2048
Это не принципиально.
можно spt_values скроссджойнить с собой, можно взять другую таблицу побольше,
пронумеровать строки ROW_NUMBER()ом. Но всё это не очень хорошо. Например, есть проблема доступа
обычных пользователей к базе master и spt_values и т.п.
Своя специальная таблмца лишена этих недостатков, её можно проиндексировать и т.д.
28 апр 12, 09:26    [12483520]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Распарсить строку  [new]
stells2
Member

Откуда: Оклахома Пригород Колымы
Сообщений: 899
* что бы не создавать нового**

Добрый день.
Столкнулся с вопросом который в других системах как-то легко решается а тут приходится что-то городить и чем дальше тем глубже :)
Суть:
Есть возможный набор строк
5695
00326-3
03264
000100-2
02303
003282
3441-1
3441-2
14650
2534-2
2534-1
25340-5
01-5
010-4

из этого должно возвращаться
5695
326
3264
100
2303
3282
3441
3441
1465
2534
2534
2534
1
10

т.е. должно быть число от 1 до 9999 (4 знака)
1. убираться ведущие нули
2. отсекаться тире и все что за ним

интересно:
002 = 2
020 = 20
00008 = 8
000080 = 80

в похожем по организации SQL - InfoPlus
это реализовано может быть, например так:
SUBSTRING(TRIM(SUBSTRING(1 OF trim(LEADING '0' from FUSNNUM) BETWEEN '-')) FROM 1 FOR 4)

где FUSNUM это поле с данными.
в Orcale за счет регулярных выражений.
А тут ничего умного не приходит в голову кроме
DECLARE  @s varchar(25);
SET @s = '00900-8';
SELECT CAST(SUBSTRING(REPLACE(SUBSTRING(@s, 1, CASE WHEN CHARINDEX('-',@s)<=0 THEN LEN(@s) ELSE CHARINDEX('-',@s) end),'-',''),1,4) as INT)

но результат не верен
90
а правильно 900
24 июн 14, 10:04    [16210164]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Minamoto
Member

Откуда: Москва
Сообщений: 1162
stells2, я бы сделал так:

select cast(case when CHARINDEX('-', @s) > 0 then substring(@s, 1, charindex('-', @s)-1) else @s end as int)
24 июн 14, 10:12    [16210210]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
Minamoto
Member

Откуда: Москва
Сообщений: 1162
stells2, ой, забыл обрезку.

Вот пример сразу с данными:

select cast(left(case when CHARINDEX('-', t1) > 0 then substring(t1, 1, charindex('-', t1)-1) else t1 end, 4) as int)
from (values ('5695'), ('00326-3'), ('03264'), ('000100-2'), ('02303'), ('003282'), ('3441-1'), ('3441-2'), ('14650'), ('2534-2'), ('2534-1'), ('25340-5'), ('01-5'), ('010-4')) as t (t1)


И, да, лучше уж новую тему завести под такой вопрос.
24 июн 14, 10:18    [16210231]     Ответить | Цитировать Сообщить модератору
 Re: Распарсить строку  [new]
stells2
Member

Откуда: Оклахома Пригород Колымы
Сообщений: 899
Minamoto
И, да, лучше уж новую тему завести под такой вопрос.

да, открыл.. Распарсить строку в 4-х значное число
там и ответил.
24 июн 14, 10:42    [16210391]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить