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

Откуда: KZ
Сообщений: 36
Всем привет! )

Вопрос по задачке:
Имеется таблица:

+

with tmp as (
	select 1 as col, '111' as val
	UNION
	select 2 as col, '1111' as val
	UNION
	select 3 as col, '11111' as val
)
select * from tmp


1 111
2 1111
3 11111



Нужно в ней каждый второй символ заменить на ноль (111) ->(101)

Я написал запрос (спасибо IAP) на одну строку (111)

+


with T(str_in, i, s_str) AS
(
		
 SELECT '111' str_in, 0 i, '' s_out
 UNION ALL
 SELECT '111', i + 1, case 
		when (i+1)%2=0 and SUBSTRING(str_in, i+1,1) = '1' then '0'
		else SUBSTRING(str_in, i+1,1)
		end 
		FROM T 
	WHERE i<LEN('111')
	
)

SELECT s_str FROM T
WHERE i > 0
ORDER BY i


1
0
1



Но это в столбец, но как сделать это встроку (STUFF и XML ?)
И как этот CTE подружить с первой таблицей?

Спасибо!
8 июн 18, 11:09    [21478381]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
шК0ДЕР
Member

Откуда: Издалека долго
Сообщений: 1205
swd1986
Нужно в ней каждый второй символ заменить на ноль (111) ->(101)

with tmp as (
	select 1 as col, '111' as val
	UNION
	select 2 as col, '1111' as val
	UNION
	select 3 as col, '11111' as val
)
select col, replace(val, '11', '10') as val from tmp
8 июн 18, 11:22    [21478416]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
swd1986
Member

Откуда: KZ
Сообщений: 36
шК0ДЕР
swd1986
Нужно в ней каждый второй символ заменить на ноль (111) ->(101)

with tmp as (
	select 1 as col, '111' as val
	UNION
	select 2 as col, '1111' as val
	UNION
	select 3 as col, '11111' as val
)
select col, replace(val, '11', '10') as val from tmp


Спасибо! Прошу прощения, уточнить хотел - данные произвольные,
select 1 as col, '1234' as val
UNION
select 2 as col, '12345' as val
UNION
select 3 as col, '123456' as val

С меня спрашивают именно умению работать с индексом строк
8 июн 18, 11:27    [21478441]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
swd1986
Member

Откуда: KZ
Сообщений: 36
swd1986
Всем привет! )

Вопрос по задачке:
Имеется таблица:

+

with tmp as (
	select 1 as col, '111' as val
	UNION
	select 2 as col, '1111' as val
	UNION
	select 3 as col, '11111' as val
)
select * from tmp


1 111
2 1111
3 11111



Нужно в ней каждый второй символ заменить на ноль (111) ->(101)

Я написал запрос (спасибо IAP) на одну строку (111)

+


with T(str_in, i, s_str) AS
(
		
 SELECT '111' str_in, 0 i, '' s_out
 UNION ALL
 SELECT '111', i + 1, case 
		when (i+1)%2=0 and SUBSTRING(str_in, i+1,1) = '1' then '0'
		else SUBSTRING(str_in, i+1,1)
		end 
		FROM T 
	WHERE i<LEN('111')
	
)

SELECT s_str FROM T
WHERE i > 0
ORDER BY i


1
0
1



Но это в столбец, но как сделать это встроку (STUFF и XML ?)
И как этот CTE подружить с первой таблицей?

Спасибо!



Получилось сделать в строку...

+
with T(str_in, i, s_str) AS
(
		
 SELECT '111' str_in, 0 i, '' s_out
 UNION ALL
 SELECT '111', i + 1, case 
		when (i+1)%2=0 and SUBSTRING(str_in, i+1,1) = '1' then '0'
		else SUBSTRING(str_in, i+1,1)
		end 
		FROM T 
	WHERE i<LEN('111')
	
)

select top 1 stuff((select s_str 
            FROM T 
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') ,1,0,'') str_out FROM t


101



Как теперь подружить с 1 ой таблицей))
8 июн 18, 11:49    [21478558]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
Kopelly
Member

Откуда: Красноярск
Сообщений: 289
swd1986,

with tmp as (
	select 1 as col, '111' as val
	UNION
	select 2 as col, '1111' as val
	UNION
	select 3 as col, '11111' as val
),
 T(col,str_in, i, s_str) AS
(
		
 SELECT col,val as str_in, 0 as i, '' as s_out	From tmp
 UNION ALL
 SELECT col,str_in, i + 1, case 
		when (i+1)%2=0 and SUBSTRING(str_in, i+1,1) = '1' then '0'
		else SUBSTRING(str_in, i+1,1)
		end 
		FROM T 
	WHERE i<LEN(str_in)
	
)

select stuff((select s_str 
            FROM T 
			Where tmp.col = t.col
			--если col не уникально использовать условие Where tmp.val = t.str_in
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') ,1,0,'') str_out FROM tmp
8 июн 18, 12:44    [21478783]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
swd1986
Member

Откуда: KZ
Сообщений: 36
Kopelly
swd1986,

with tmp as (
	select 1 as col, '111' as val
	UNION
	select 2 as col, '1111' as val
	UNION
	select 3 as col, '11111' as val
),
 T(col,str_in, i, s_str) AS
(
		
 SELECT col,val as str_in, 0 as i, '' as s_out	From tmp
 UNION ALL
 SELECT col,str_in, i + 1, case 
		when (i+1)%2=0 and SUBSTRING(str_in, i+1,1) = '1' then '0'
		else SUBSTRING(str_in, i+1,1)
		end 
		FROM T 
	WHERE i<LEN(str_in)
	
)

select stuff((select s_str 
            FROM T 
			Where tmp.col = t.col
			--если col не уникально использовать условие Where tmp.val = t.str_in
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') ,1,0,'') str_out FROM tmp


Обалдеть! А я уже отчаялся, такого понаписал)) Kopelly - спасибо!!!))
8 июн 18, 12:53    [21478837]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
шК0ДЕР
Member

Откуда: Издалека долго
Сообщений: 1205
swd1986
Спасибо! Прошу прощения, уточнить хотел - данные произвольные

Ваш пример реализации этому противоречит...
Не проще ли для универсальности написать функцию?
Первое, что пришло в голову...
create function [dbo].[Replacer] (@Str    varchar(max),
                                  @Symbol varchar(1))  
returns varchar(max)  
with execute as caller  
as  
begin  
  declare @Result varchar(max) = ''
  while ceiling((len(@Str) / 2.0)) <> 0
  begin
	select @Result = @Result + left(@str, 1) + case when len(@str) > 1 then @Symbol else '' end, 
	       @Str = substring(@Str, 2 + 1, len(@Str))
  end
  return @Result
end

А потом просто подставить
with tmp (col, val) as (
	select 1, '1234'   union all
        select 2, '12345'  union all
        select 3, '123456' union all
	select 4, '111'    union all
	select 5, '1111'   union all
	select 6, '11111'  union all
	select 7, '0'      union all
	select 8, '')
select col, 
       dbo.Replacer(val, '0') as val 
  from tmp


1	1030
2	10305
3	103050
4	101
5	1010
6	10101
7	0
8	
8 июн 18, 12:56    [21478856]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
swd1986
Member

Откуда: KZ
Сообщений: 36
шК0ДЕР,

Я извиняюсь перед Вами) это просто я не донес подробности задачи

Ну и я был бы очень рад использовать процедуры/функции, но мне не разрешают этого делать )))

Такие вот задачки...
8 июн 18, 13:20    [21478962]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
шК0ДЕР
Member

Откуда: Издалека долго
Сообщений: 1205
swd1986
я был бы очень рад использовать процедуры/функции, но мне не разрешают этого делать
А зря...
8 июн 18, 13:25    [21478993]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
invm
Member

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

А что разрешают?
8 июн 18, 14:10    [21479202]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
swd1986
Member

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

А что разрешают?


Только CTE )
8 июн 18, 14:19    [21479238]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
лолл
Member

Откуда:
Сообщений: 450
шК0ДЕР, вашу функцию можно легко переписать через рекурсивное CTE
8 июн 18, 14:34    [21479287]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
invm
Member

Откуда: Москва
Сообщений: 9343
swd1986
Только CTE )
with d as
(
 select
  col, val
 from
  (values (1, '1234'), (2, '12345'), (3, '123456')) t(col, val)
),
n as
(
 select 1 as n, max(len(val)) as ml from d

 union all

 select
  n + 1, ml
 from
  n
 where
  n <= n.ml
)
select
 d.col, d.val, a.x.value('.', 'varchar(max)')
from
 d cross apply
 (
  select
   case (n - 1) % 2 when 1 then '0' else substring(d.val, n.n, 1) end
  from
   n
  where
   n.n <= len(d.val)
  for xml path(''), type
 ) a(x);
8 июн 18, 14:47    [21479344]     Ответить | Цитировать Сообщить модератору
 Re: И опять вопрос про CTE  [new]
swd1986
Member

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

+
invm
swd1986
Только CTE )
with d as
(
 select
  col, val
 from
  (values (1, '1234'), (2, '12345'), (3, '123456')) t(col, val)
),
n as
(
 select 1 as n, max(len(val)) as ml from d

 union all

 select
  n + 1, ml
 from
  n
 where
  n <= n.ml
)
select
 d.col, d.val, a.x.value('.', 'varchar(max)')
from
 d cross apply
 (
  select
   case (n - 1) % 2 when 1 then '0' else substring(d.val, n.n, 1) end
  from
   n
  where
   n.n <= len(d.val)
  for xml path(''), type
 ) a(x);


Спасибо тебе большущее! Оооофигеть запрос) И кстати, кое что узнал из этого запроса!

Спасибо!!!!!
8 июн 18, 14:57    [21479391]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить