powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / CTE и промежуточные результаты выполнения
9 сообщений из 9, страница 1 из 1
CTE и промежуточные результаты выполнения
    #39659402
swd1986
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет товарищи!
Хочу выразить спасибо тем, кто решил помочь мне в решении данной задачи
А именно я пытаюсь разобраться все в том же CTE,
я знаю, желание убивать у посвященных людей на этом форуме только увеличивается! ))

меня озадачили такой фишкой с CTE, имеется таблица - с индексом и строкой
которая "якобы"
показывает бинарную последовательность 0 или 1

Код: sql
1.
2.
3.
4.
5.
6.
with binaries as 
(
	SELECT 1 as id, '1101101' as bin
	UNION 
	SELECT 2 as id, '0111011' as bin
),



так вот, суть задачи: Провести "инверсию" в строке посимвольно, т.е.
следующий символ это инверсия от предыдущего если этот символ равен 1.
Если символ равен 0, то копируем предыдущий
Например:
'1101101' ->
первый равен 1 - первая позиция - не трогаем (1)
второй 1 - равен инверсией от первого (10)
третий 0 - копируем предыдущий (100)
4 - 1 инверсия 3-ого = (1001)
5 - 1 инверсия 4 -ого = (10010)
6 - 0 копируем пред (100100)
7 - 1 инверс 6 ого (1001001)

казалось бы вообще фигня
я понял как работает CTE

http://www.sql.ru/forum/1295380/sql-i-matrica-realno-li-reshit-takuu-zadachu
http://www.sql.ru/forum/1295471/i-opyat-vopros-pro-cte


пишу вот такой запрос:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
T(id,str_in, i, s_str) AS
(
		
 SELECT id, bin as str_in, 0 as i, '' as s_out	From binaries
 UNION ALL
 SELECT id,str_in, i + 1, case 
		when i=0  then  SUBSTRING(str_in, i, 1) --если это первый символ - не трогаем
		when i>0 and SUBSTRING(str_in, i, 1) = '1' and SUBSTRING(str_in, i-1, 1) = '0' then '1' -- если предыдущий равен 0 то 1
		when i>0 and SUBSTRING(str_in, i, 1) = '1' and SUBSTRING(str_in, i-1, 1) = '1' then '0' -- наоборот
		when i>0 and SUBSTRING(str_in, i, 1) = '0' then SUBSTRING(str_in, i-1, 1) -- если равен 0, то копируем
		end 
		FROM T 
	WHERE i<=LEN(str_in)
)

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




но тут то уже мой воспаленный мозг понял, что данные берущие из binaries
не меняются в CTE. В этом и есть загвоздка, как придумать некий "буфер"
и ложить туда данные для выполнения промежуточных операции со строками?

или вообще возможно ли такое в принципе?

я пробую многократно cross joinить с предусловиями... Но и это мне кажется обречено на позорное фиаско)

PS: Решение только при помощи with, select, CTE

Или этими средствами можно ли выполнить как то итерацию по строкам c учетом изменении "на лету"?
...
Рейтинг: 0 / 0
CTE и промежуточные результаты выполнения
    #39659412
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это нереляционная задача.

1. Разобрать строку бит в столбец бит и порядковый номер.
2. Запросом с LEAD сгенерировать новый столбец бит.
3. Сложить все обратно в бинари.

А так-то изложенный алгоритм =
Код: vbnet
1.
2.
3.
b(0) = 0
for i:=1 to N
  b(i) = b(i) or b(i-1)
...
Рейтинг: 0 / 0
CTE и промежуточные результаты выполнения
    #39659413
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
пардон, не or, а xor.
...
Рейтинг: 0 / 0
CTE и промежуточные результаты выполнения
    #39659416
swd1986
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222Это нереляционная задача.

1. Разобрать строку бит в столбец бит и порядковый номер.
2. Запросом с LEAD сгенерировать новый столбец бит.
3. Сложить все обратно в бинари.

А так-то изложенный алгоритм =
Код: vbnet
1.
2.
3.
b(0) = 0
for i:=1 to N
  b(i) = b(i) or b(i-1)




Спасибо! LAG и LEAD, это классная идея! Попробую сейчас....
...
Рейтинг: 0 / 0
CTE и промежуточные результаты выполнения
    #39659418
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
swd1986,

Код: 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.
with binaries as 
(
	SELECT 1 as id, '1101101' as bin
	UNION 
	SELECT 2 as id, '0111011' as bin
),
t as
(
 select
  1 as p, id, bin,
  left(bin, 1) as c from binaries
 union all
 select
  t.p + 1, t.id, t.bin,
  case
   when a.c = '0' then t.c
   when a.c = '1' and t.c = '0' then '1'
   when a.c = '1' and t.c = '1' then '0'
  end
 from
  t join
  binaries b on b.id = t.id cross apply
  (select substring(b.bin, t.p + 1, 1)) a(c)
 where
  t.p < len(b.bin)
)
select
 b.*, a.x.value('.', 'varchar(30)')
from
 binaries b cross apply
 (
  select
   c as [*]
  from
   t
  where
   id = b.id
  order by
   p
  for xml path(''), type
 ) a(x);
...
Рейтинг: 0 / 0
CTE и промежуточные результаты выполнения
    #39659425
swd1986
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invmswd1986,

Код: 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.
with binaries as 
(
	SELECT 1 as id, '1101101' as bin
	UNION 
	SELECT 2 as id, '0111011' as bin
),
t as
(
 select
  1 as p, id, bin,
  left(bin, 1) as c from binaries
 union all
 select
  t.p + 1, t.id, t.bin,
  case
   when a.c = '0' then t.c
   when a.c = '1' and t.c = '0' then '1'
   when a.c = '1' and t.c = '1' then '0'
  end
 from
  t join
  binaries b on b.id = t.id cross apply
  (select substring(b.bin, t.p + 1, 1)) a(c)
 where
  t.p < len(b.bin)
)
select
 b.*, a.x.value('.', 'varchar(30)')
from
 binaries b cross apply
 (
  select
   c as [*]
  from
   t
  where
   id = b.id
  order by
   p
  for xml path(''), type
 ) a(x);



invm,

Большущее спасибо! Это как раз та ситуация, когда ученик идет в гору,
на вершине которого сидит мастер. Даже не мастер, а учитель.
Вообщем то, для учителя выгода получить удовлетворение от безвозмездно
переданных знании ученику. А ученик, знания которого в руках, дает учителю
признание. Ну и осознание ученику, какой же он "д****б" ))

я честно ждал такого запроса, правильнее было мучиться, париться, но добиться
своего или потерпеть фи.sql.аско. А тут и разобрать код, и понять как работает, и
главное - сэкономленное время. На блюдечке в голубой каемочке...

Еще раз спасибо invm и сайту)
...
Рейтинг: 0 / 0
CTE и промежуточные результаты выполнения
    #39659427
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmswd1986,

Код: 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.
with binaries as 
(
	SELECT 1 as id, '1101101' as bin
	UNION 
	SELECT 2 as id, '0111011' as bin
),
t as
(
 select
  1 as p, id, bin,
  left(bin, 1) as c from binaries
 union all
 select
  t.p + 1, t.id, t.bin,
  case
   when a.c = '0' then t.c
   when a.c = '1' and t.c = '0' then '1'
   when a.c = '1' and t.c = '1' then '0'
  end
 from
  t join
  binaries b on b.id = t.id cross apply
  (select substring(b.bin, t.p + 1, 1)) a(c)
 where
  t.p < len(b.bin)
)
select
 b.*, a.x.value('.', 'varchar(30)')
from
 binaries b cross apply
 (
  select
   c as [*]
  from
   t
  where
   id = b.id
  order by
   p
  for xml path(''), type
 ) a(x);


Очень забавно городить целый case для банального xor.

Ваще то, если напрячь фантазию:

Код: vbnet
1.
2.
3.
4.
5.
6.
 new_b(i) = old_b(i) xor new_b(i-1)

 new_b(i) = old_b(i) xor ( old_b(i-1) xor new_b(i-2) )
...

 new_b(i) = old_b(i) xor old_b(i-1) xor ... xor old_b(1)



и задача становится почти реляционной, т.е. новое значение бита может быть рассчитано исключительно из текущих значений бит.
...
Рейтинг: 0 / 0
CTE и промежуточные результаты выполнения
    #39659430
swd1986
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222
invmswd1986,

Код: 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.
with binaries as 
(
	SELECT 1 as id, '1101101' as bin
	UNION 
	SELECT 2 as id, '0111011' as bin
),
t as
(
 select
  1 as p, id, bin,
  left(bin, 1) as c from binaries
 union all
 select
  t.p + 1, t.id, t.bin,
  case
   when a.c = '0' then t.c
   when a.c = '1' and t.c = '0' then '1'
   when a.c = '1' and t.c = '1' then '0'
  end
 from
  t join
  binaries b on b.id = t.id cross apply
  (select substring(b.bin, t.p + 1, 1)) a(c)
 where
  t.p < len(b.bin)
)
select
 b.*, a.x.value('.', 'varchar(30)')
from
 binaries b cross apply
 (
  select
   c as [*]
  from
   t
  where
   id = b.id
  order by
   p
  for xml path(''), type
 ) a(x);


Очень забавно городить целый case для банального xor.

Ваще то, если напрячь фантазию:

Код: vbnet
1.
2.
3.
4.
5.
6.
 new_b(i) = old_b(i) xor new_b(i-1)

 new_b(i) = old_b(i) xor ( old_b(i-1) xor new_b(i-2) )
...

 new_b(i) = old_b(i) xor old_b(i-1) xor ... xor old_b(1)



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

Спасибо! Но invm показал запрос, который может применяться не только к битовым значениям. Это первое, второе - это как раз таки тот случай "как меняются данные на лету" средствами CTE (один из вариантов решения)... Порой мне кажется человек, который дал мне задачу и invm - это один и тот же чел )
...
Рейтинг: 0 / 0
CTE и промежуточные результаты выполнения
    #39659432
swd1986
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
swd1986,

PS: Тапак еще выручал, он тоже умеет отжигать)
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / CTE и промежуточные результаты выполнения
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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