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

Откуда:
Сообщений: 68
Здравствуйте, уважаемые форумчане!
Понимаю, что тема неоднократно всплывала на форуме, но мои попытки перенести чужие идеи на сою таблицу усехом не увенчались.
Буду очень благодарен если поможете решить следующую задачку:
Таблица следующего вида
ZagotMain.dbo со столбцами KE, ZagOnQTY,ZagName,ZagNotices, ZagVariantObesp,ZagDimensions,ZagClassProfil,ZagMatLongName,ZagVersion
для упрощения выберем три:
(Zagname |Zagid | zagdimesions)
фланец | 123 | длина*=12 плотность*=7500 диаметр*=20 |

Мне нужно разделить столбец zagdimensions на три, т.е. на выходе таблица должна получится вида
Zagname | Zagid| длина | плотность | диаметр |
фланец | 123 | 12 | 7500 | 12 |


пробывал решить так :
select AF.*,bb.s
from
 ( 
 select A.KE, ZagOnQTY,ZagName,ZagNotices, ZagVariantObesp,ZagDimensions,ZagClassProfil,ZagMatLongName,ZagVersion
  from dbo.ZVZD_VM_Zagot_Main A
  inner join
  (
  select KE, MAX(zagversion) as ver
  from dbo.ZVZD_VM_Zagot_Main
  group by ke 
  )B on b.KE=A.KE and B.ver=A.ZagVersion 
  where ZagVariantObesp > 1 and ZagClassProfil like 'круг%' --order by ZagVersion desc 
  ) AF
 inner join
 ( 
 (select KE,ZagOnQTY, ZagName,ZagNotices, ZagVariantObesp,ZagDimensions,ZagClassProfil,ZagMatLongName,ZagVersion,
    SUBSTRING (zagdimensions, 26,3)  as s
    FROM dbo.ZVZD_VM_Zagot_Main
    where SUBSTRING (zagdimensions, 26,3) > '55' )
    ) bb on bb.KE=AF.KE
   and af.ZagOnQTY  > '1' 


В принципе работает, но только в том случае если в исходном столбце все стоит на своих местах и в нужной последовательности, то есть размеры всегда двухзначные, а в самом столбце плотность с длиной не меняются местами (есть где сначала идет длина плотность диаметр, а есть где плотность диаметр длина).
Мне бы только разделить, а проверить на соответствие условиям я смогу).

Вообще реально это сделать средствами sql ?

Сообщение было отредактировано: 27 авг 14, 14:07
27 авг 14, 12:24    [16499426]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
--__Александр__--
Member

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

Строку парсить надо. Сначала, надо определиться по каким критериям будем выделять столбец и значение.
Если, например значение для плотности ВСЕГДА лежит между плотность*= и пробел,
то юзаете charindex + substring.
declare @str varchar(max)
declare @SerchP varchar(max)

set @str = 'длина*=12 плотность*=7500 диаметр*=20'
set @SerchP = ' плотность*='


select substring( ltrim(substring( @str
                                 , charindex(@SerchP,@str)  + len(@SerchP)
                                 , len(@str) )
                       )
                , 0
                , charindex(' ',ltrim(substring( @str
                                     , charindex(@SerchP,@str)  + len(@SerchP)
                                     , len(@str) )
                                     )
                           )
                )


Если внутренности могут быть не структурированы, то более сложный парсинг уже с поиском первой не цифры.
27 авг 14, 12:49    [16499682]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

Откуда:
Сообщений: 68
--__Александр__--,

Спасибо за ответ, попробую разобраться
27 авг 14, 14:11    [16500735]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

Откуда:
Сообщений: 68
в общем по сути мне надо получить значения длины плотности диаметра для того чтобы в последствии посмотреть будут ли размеры удовлетворять условия... Но! Может быть есть возможность не разделяя столбец на три проверить на соответсвие каждой из строк условию.
Пример:
по условию круги у которых диаметр меньше 55 и длина меньше 50 мне не нужны.
в столбце ZagDimensions такие данные:
диаметр*=60 плотность*=7500 длина*=30
плотность=7500 диаметр*=30 длина*=20
у каждой строки имеется свой ZAGid. Мне нужно чтобы столбец ZafDimensions либо разбился на три, либо чтобы не разбивая столбец выделить строки удовлетворяющие условие. Строки не структурированы я так понимаю, потому что в одной сначала диаметр, во второй сначала плотность и тд
27 авг 14, 14:41    [16501048]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
--__Александр__--
Member

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

разобраться не получилось?
27 авг 14, 15:11    [16501461]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
invm
Member

Откуда: Москва
Сообщений: 9406
Вот вам в качестве идеи:
declare @t table (Zagname varchar(100), Zagid int,  zagdimesions varchar(8000))
insert into @t
values
 ('фланец1', 123, 'длина*=12 плотность*=7500 диаметр*=20'),
 ('фланец2', 124, 'плотность*=7500 длина*=12 диаметр*=20');

select
 t.*,
 x.n.value('длина[1]/@value', 'int') as [длина],
 x.n.value('диаметр[1]/@value', 'int') as [диаметр],
 x.n.value('плотность[1]/@value', 'int') as [плотность]
from
 @t t cross apply
 (select cast('<' + replace(replace(t.zagdimesions, ' ', '"/><'), '*=', ' value="') + '"/>' as xml)) a(v) cross apply
 a.v.nodes('/') x(n);
27 авг 14, 15:13    [16501490]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

Откуда:
Сообщений: 68
--__Александр__--,

вот вот, не без помощи добрых людей! сейчас продемонстрирую
27 авг 14, 15:13    [16501492]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

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

Спасибо огромное!!! сейчас попробую!
27 авг 14, 15:17    [16501536]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
AANovikov
длины плотности диаметра
???
27 авг 14, 15:34    [16501728]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
iap
AANovikov
длины плотности диаметра
???

enlarge your.....
27 авг 14, 15:42    [16501794]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

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

ну да. В столбце ZagDimensions прописаны параметры: длина*=12 плотность*=1750 диаметр*=21. Мне нужно получить именно цифры разбитые по наименованию параметров(|длина|плотность|диаметр|)
27 авг 14, 16:05    [16502043]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

Откуда:
Сообщений: 68
--__Александр__--,

спасибо вам еще раз!!!
Сделал примерно как вы написали но не совсем. единственное "но" заключается в том что не получается получить значение параметра для всех id сразу. Вот как получилось:
declare @s nvarchar(max)
declare @par nvarchar(max)
declare @start int
declare @fin int
set @par='диаметр*'
set @s=(select [zagdimensions] from [dbo].[ZVZD_VM_Zagot_Main] where [zagid]=907)
--select @s
set @start=(select CHARINDEX(@par, @s))+LEN(@par)+1
--select @start
set @fin=(select CHARINDEX(' ',substring(@s,@start,LEN(@s)-@start)))
--select @fin
if @fin=0
begin
select SUBSTRING(@s,@start,LEN(@s)-@start+1)
end
else
begin
select SUBSTRING(@s,@start,@fin-1)
end
27 авг 14, 16:08    [16502089]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
Glory
Member

Откуда:
Сообщений: 104760
AANovikov
единственное "но" заключается в том что не получается получить значение параметра для всех id сразу

Надо среди сотни тем форума, в которых обсуждался парсинг строк, найти темы с примерами готовых функций.
27 авг 14, 16:14    [16502144]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
--__Александр__--
Member

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

Потому что сетами надо думать, а не построчно.
declare @t table (Zagname varchar(100), Zagid int,  zagdimesions varchar(8000))
insert into @t
values
 ('фланец1', 123, 'длина*=17 плотность*=7500 диаметр*=20'),
 ('фланец2', 124, 'плотность*=7500 длина*=12 диаметр*=20');

select Zagid, Zagname
     , [плотность] =  substring( ltrim(substring( zagdimesions
                                 , charindex('плотность*=',zagdimesions)  + len('плотность*=')
                                 , len(zagdimesions) )
                       )
                , 0
                , charindex(' ',ltrim(substring( zagdimesions
                                     , charindex('плотность*=',zagdimesions)  + len('плотность*=')
                                     , len(zagdimesions) )
                                     )
                           )
                )
    , [длина] =  substring( ltrim(substring( zagdimesions
                                 , charindex('длина*=',zagdimesions)  + len('длина*=')
                                 , len(zagdimesions) )
                       )
                , 0
                , charindex(' ',ltrim(substring( zagdimesions
                                     , charindex('длина*=',zagdimesions)  + len('длина*=')
                                     , len(zagdimesions) )
                                     )
                           )
                ) 
  from @t


Вообще, лучше логику парсинга в функу обернуть.

create function dbo.fPars(@Str varchar(max), @P varchar(50))
returns table
as return ( select S = substring( ltrim(substring( @Str
                                 , charindex(@P,@Str)  + len(@P)
                                 , len(@Str) )
                       )
                , 0
                , IsNull( NullIf(
                          charindex(' ',ltrim(substring( @Str
                                             , charindex(@P,@Str)  + len(@P)
                                             , len(@Str) )
                                             )
                                   ),0),len(@Str))
                ) 
)

Если логика более сложная, то уже в скалярную/мульти стейтмент.
И тогда так:
select * 
  from @t
cross apply dbo.fPars(zagdimesions,'длина*=') S1
cross apply dbo.fPars(zagdimesions,'плотность*=') S2
cross apply dbo.fPars(zagdimesions,'диаметр*=') S3
27 авг 14, 16:25    [16502246]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

Откуда:
Сообщений: 68
--__Александр__--,

большое спасибо за совет! попробую переварить! Я поражен скоростью получения ответов на этом форуме, первый опыт, первая щетина, первое опьянение ))) спасибо
27 авг 14, 16:38    [16502343]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

Откуда:
Сообщений: 68
Господа, профи! Времени почти не было на то чтобы довести до ума начатое... в общем проблема на данный момент заключается в том что у меня не получается вывести значения для всех id сразу! если в 6ой строчке меняю zagid=907 на zagid>907 sql начинает ругаться и выдает следующее сообщение:"Сообщение 512, уровень 16, состояние 1, строка 6
Вложенный запрос вернул больше одного значения. Это запрещено, когда вложенный запрос следует после =, !=, <, <=, >, >= или используется в качестве выражения.

(строк обработано: 1)".
Подскажите как быть... у меня ступор и я новичок

declare @s nvarchar(max)
declare @par nvarchar(max)
declare @start int
declare @fin int
set @par='диаметр*'
set @s=(select [zagdimensions] from [dbo].[ZVZD_VM_Zagot_Main] where [zagid]=907)
--select @s
set @start=(select CHARINDEX(@par, @s))+LEN(@par)+1
--select @start
set @fin=(select CHARINDEX(' ',substring(@s,@start,LEN(@s)-@start)))
--select @fin
if @fin=0
begin
select SUBSTRING(@s,@start,LEN(@s)-@start+1)
end
else
begin
select SUBSTRING(@s,@start,@fin-1)
end
4 сен 14, 13:12    [16534553]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
Glory
Member

Откуда:
Сообщений: 104760
AANovikov
set @s=(select [zagdimensions] from [dbo].[ZVZD_VM_Zagot_Main] where [zagid]=907)

Зачем вы пытаетесь в переменную записать набор значений ?
Вам уже написали готовый запрос "для всех id сразу!"
4 сен 14, 13:16    [16534578]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

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

если вы про это, то тут у меня проблема в том что мне не понятно как для всей таблицы сразу значения вывести не вбивая значения каждой ячейки...
declare @t table (Zagname varchar(100), Zagid int, zagdimesions varchar(8000))
insert into @t
values
('фланец1', 123, 'длина*=17 плотность*=7500 диаметр*=20'),
('фланец2', 124, 'плотность*=7500 длина*=12 диаметр*=20');

select Zagid, Zagname
, [плотность] = substring( ltrim(substring( zagdimesions
, charindex('плотность*=',zagdimesions) + len('плотность*=')
, len(zagdimesions) )
)
, 0
, charindex(' ',ltrim(substring( zagdimesions
, charindex('плотность*=',zagdimesions) + len('плотность*=')
, len(zagdimesions) )
)
)
)
, [длина] = substring( ltrim(substring( zagdimesions
, charindex('длина*=',zagdimesions) + len('длина*=')
, len(zagdimesions) )
)
, 0
, charindex(' ',ltrim(substring( zagdimesions
, charindex('длина*=',zagdimesions) + len('длина*=')
, len(zagdimesions) )
)
)
)
from @t

А если про это, то тут у меня ругается sql! говорит: "синтаксическая ошибка и "create function" должна быть единственной в пакете".

create function dbo.fPars(@Str varchar(max), @P varchar(50))
returns table
as return ( select S = substring( ltrim(substring( @Str
, charindex(@P,@Str) + len(@P)
, len(@Str) )
)
, 0
, IsNull( NullIf(
charindex(' ',ltrim(substring( @Str
, charindex(@P,@Str) + len(@P)
, len(@Str) )
)
),0),len(@Str))
)
)
Прошу вас, только не ругайтесь... я имею кое какое представление о написании запросов, но не хватает. Вам как специалисту наверняка надоело отвечать на глупые вопросы, но все таки хотелось бы решить задачу!
4 сен 14, 14:17    [16535075]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
Glory
Member

Откуда:
Сообщений: 104760
AANovikov
если вы про это, то тут у меня проблема в том что мне не понятно как для всей таблицы сразу значения вывести не вбивая значения каждой ячейки...

А кто вас завставляет вбивать "значения каждой ячейки" ?

Сообщение было отредактировано: 4 сен 14, 14:21
4 сен 14, 14:21    [16535092]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
o-o
Guest
AANovikov
А если про это, то тут у меня ругается sql! говорит: "синтаксическая ошибка и "create function" должна быть единственной в пакете".

"единственное в пакете" означает, что до этого кода ничего нету или написано GO.
выделите только текст ф-ции, потом Execute.
или закомментируйте всe, что ДО ф-ции.
или в новое окно текст ф-ции скопируйте
4 сен 14, 14:28    [16535135]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
Glory
Member

Откуда:
Сообщений: 104760
select
 t.*,
 x.n.value('длина[1]/@value', 'int') as [длина],
 x.n.value('диаметр[1]/@value', 'int') as [диаметр],
 x.n.value('плотность[1]/@value', 'int') as [плотность]
from
 ВОТ_ТУТ_ВОТ_ДОЛЖНО_БЫТЬ_ИМЯ_МОЕЙ_ТАБЛИЦЫ t cross apply
 (select cast('<' + replace(replace(t.zagdimesions, ' ', '"/><'), '*=', ' value="') + '"/>' as xml)) a(v) cross apply
 a.v.nodes('/') x(n);
4 сен 14, 14:41    [16535224]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

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

Спасибо вам! Получилось следующим образом решить задачу :

create function TestFunc(@zagid int)
returns nvarchar(50)
as
begin
declare @s nvarchar(max)
declare @par nvarchar(max)
declare @start int
declare @fin int
declare @res nvarchar(50)
set @par='диаметр*'
set @s=(select [zagdimensions] from [dbo].[ZVZD_VM_Zagot_Main] where [zagid]=@zagid)
--select @s
set @start=(select CHARINDEX(@par, @s))+LEN(@par)+1
--select @start
set @fin=(select CHARINDEX(' ',substring(@s,@start,LEN(@s)-@start)))
--select @fin
if @fin=0
begin
set @res=(select SUBSTRING(@s,@start,LEN(@s)-@start+1))
end
else
begin
set @res=(select SUBSTRING(@s,@start,@fin-1))
end
return @res
end

select dbo.TestFunc(907,'длина*')

select zagid,
dbo.TestFunc(zagid,'длина*'),
ZagDimensions
from dbo.ZVZD_VM_Zagot_Main
where ZagID between 900 and 1200

работает, все что нужно выдает... вдруг полезно будет кому
4 сен 14, 15:55    [16535818]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
Glory
Member

Откуда:
Сообщений: 104760
AANovikov
вдруг полезно будет кому

такой говнокод никому не нужен.
4 сен 14, 15:57    [16535829]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

Откуда:
Сообщений: 68
прошу прощения за оформление и да простит меня модератор(?!),но на форумах до этого не сидел и с тэгами не сталкивался, попробую конечно, но за результат не отвечаю
[/SRC]
create function TestFunc(@zagid int)
returns nvarchar(50)
as
begin
declare @s nvarchar(max)
declare @par nvarchar(max)
declare @start int
declare @fin int
declare @res nvarchar(50)
set @par='диаметр*'
set @s=(select [zagdimensions] from [dbo].[ZVZD_VM_Zagot_Main] where [zagid]=@zagid)
--select @s
set @start=(select CHARINDEX(@par, @s))+LEN(@par)+1
--select @start
set @fin=(select CHARINDEX(' ',substring(@s,@start,LEN(@s)-@start)))
--select @fin
if @fin=0
begin
set @res=(select SUBSTRING(@s,@start,LEN(@s)-@start+1))
end
else
begin
set @res=(select SUBSTRING(@s,@start,@fin-1))
end 
return @res
end

select dbo.TestFunc(907,'длина*')

select zagid,
dbo.TestFunc(zagid,'длина*'),
ZagDimensions
from dbo.ZVZD_VM_Zagot_Main
where ZagID between 900 and 1200
[src]
4 сен 14, 15:59    [16535839]     Ответить | Цитировать Сообщить модератору
 Re: разделить столбец  [new]
AANovikov
Member

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

ну я же не профи, как некоторые... мне все равно, главное что работает
4 сен 14, 16:01    [16535849]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить