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

Откуда:
Сообщений: 316
Есть необходимость итерировать по записям, которые возвращает запрос. В зависимости от значения в одном поле, нужно изменить другие поля.

Допустим, если поле а текущей записи имеет значение 5, то значение полей b и c устанавливаются в 5+10 и 5+20 соответственно. Пример утрированный.

Какие есть варианты?
20 июл 14, 16:13    [16331374]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
aleks2
Guest
select a
       , case a when 5 then 5+10 else b end as b
       , case a when 5 then 5+20 else c end as c
   from aTable;
20 июл 14, 16:23    [16331403]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

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

поле а - это зачения ID, их очень много, на каждый case - сами понимаете...
20 июл 14, 16:53    [16331473]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
iap
Member

Откуда: Москва
Сообщений: 47063
_Novichok
aleks2,

поле а - это зачения ID, их очень много, на каждый case - сами понимаете...
А чем же здесь поможет цикл?
Надо эти новые значения полей в зависимости от ID собрать в табличное выражение и применить JOIN.
20 июл 14, 17:05    [16331499]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

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

На данный момент рассматриваю вариант с курсором.
Правда где-то читал, что курсоры нужно применять только при крайней необходимости.
Значение в анализируемом поле парсится, происходят дополнительные вычисления и только потом происходят обновления, то есть, с каждой записью нужно работать отдельно
20 июл 14, 18:06    [16331648]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
aleks2
Guest
_Novichok
На данный момент рассматриваю вариант с курсором.
Правда где-то читал, что курсоры нужно применять только при крайней необходимости.
Значение в анализируемом поле парсится, происходят дополнительные вычисления и только потом происходят обновления, то есть, с каждой записью нужно работать отдельно


Глупенький, курсор не нужен.
20 июл 14, 18:11    [16331659]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

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

aleks2
Глупенький, курсор не нужен.

ну, не надо обзываться. :(

Каким образом тогда все это делать? Обновления записей происходит не в той же строке, а в других строках этой же таблицы. Значения каких строк должны измениться - вычисляется как раз на основе одного из полей текуйщей строки, и это не простые числовые значения, а строковые, которые предварительно нужно распарсить.
Что вы предлагаете?
20 июл 14, 18:56    [16331779]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
gandjustas
Member

Откуда:
Сообщений: 857
Блог
_Novichok
Есть необходимость итерировать по записям, которые возвращает запрос. В зависимости от значения в одном поле, нужно изменить другие поля.

Допустим, если поле а текущей записи имеет значение 5, то значение полей b и c устанавливаются в 5+10 и 5+20 соответственно. Пример утрированный.

Какие есть варианты?


Лучше расскажи какую проблему ты пытаешься решить таким образом. Скорее всего ты не с той стороны зашел.
20 июл 14, 19:00    [16331797]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_human
Member

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

cross apply
20 июл 14, 19:00    [16331798]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

Откуда:
Сообщений: 316
id a c b
5556;57P25
565625
575725

1. каждая а предварительно парсится (количество значений через запятую может быть неограниченным)
2. Вычисляется, какую запись изменять (по сути а - это набор id. Да я знаю, БД не нормализированная ни в одну форму, - она мне самому не нравится).
3. В той записи, где парсилось, в b устанавливается P(Parent)+номер
4. В тех записях, id которыx были расперсенные, в c устанавливается номер.
20 июл 14, 19:39    [16331926]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
gandjustas
Member

Откуда:
Сообщений: 857
Блог
_Novichok
id a c b
5556;57P25
565625
575725

1. каждая а предварительно парсится (количество значений через запятую может быть неограниченным)
2. Вычисляется, какую запись изменять (по сути а - это набор id. Да я знаю, БД не нормализированная ни в одну форму, - она мне самому не нравится).
3. В той записи, где парсилось, в b устанавливается P(Parent)+номер
4. В тех записях, id которыx были расперсенные, в c устанавливается номер.


1) Сделай CLR Table Valued Function, которая парсит значения a
2) Сделай select и outer apply на твою функцию, заверни в CTE. Прямо в selct укажи новые значения для с и b.
3) Сделай update используя полученный CTE
20 июл 14, 19:59    [16331977]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

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

спасибо, попробую так, как вы описали, и все-таки попробую с курсором: как будет быстрее - производительность тоже имеет значение
20 июл 14, 20:52    [16332113]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
gandjustas
Member

Откуда:
Сообщений: 857
Блог
_Novichok
gandjustas,

спасибо, попробую так, как вы описали, и все-таки попробую с курсором: как будет быстрее - производительность тоже имеет значение


С курсором гарантированно медленнее.
20 июл 14, 21:19    [16332178]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

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

Каким образом
gandjustas
2) Прямо в selct укажи новые значения для с и b.
?
21 июл 14, 17:50    [16337107]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
aleks2
Guest
_Novichok
gandjustas,

Каким образом
gandjustas
2) Прямо в selct укажи новые значения для с и b.
?


Таким же, как ты собираешься это делать в курсоре.
21 июл 14, 17:52    [16337116]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

Откуда:
Сообщений: 316
курсор я могу использовать в цикле, работая с каждой записью отдельно, тем более, что значение b - это значение счетчика.
Как завернуть его в этот CTE и заполнить данное поле - не могу понять
21 июл 14, 18:04    [16337188]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_djХомяГ
Guest
Давно функцию опубликовывал aleks2
Вот пример
разобрать текст
21 июл 14, 18:04    [16337190]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_djХомяГ
Guest
Либо круить цикл - все зависит от версии сервера >=2005 или <2005
21 июл 14, 18:05    [16337197]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

Откуда:
Сообщений: 316
Microsoft SQL Server 2008 R2 (SP2) - 10.50.4000.0 (X64)
Jun 28 2012 08:36:30
Copyright (c) Microsoft Corporation
Express Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: ) (Hypervisor)
21 июл 14, 18:16    [16337253]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_djХомяГ
Guest
Тогда ф-ция с CTE + cross/outer apply вместо курсора (собственно как говорили выше)
21 июл 14, 18:19    [16337270]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

Откуда:
Сообщений: 316
_djХомяГ
Тогда ф-ция с CTE + cross/outer apply вместо курсора (собственно как говорили выше)

так это уже реализовано. теперь стоит вопрос, как обновить таблицу новыми данными
21 июл 14, 18:25    [16337297]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
aleks2
Guest
_Novichok
_djХомяГ
Тогда ф-ция с CTE + cross/outer apply вместо курсора (собственно как говорили выше)

так это уже реализовано. теперь стоит вопрос, как обновить таблицу новыми данными


Напишите же ему update, хто-нибудь гуманный.
21 июл 14, 18:36    [16337346]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

Откуда:
Сообщений: 316
gandjustas
1) Сделай CLR Table Valued Function, которая парсит значения a
2) Сделай select и outer apply на твою функцию, заверни в CTE. Прямо в selct укажи новые значения для с и b.
3) Сделай update используя полученный CTE

имею на входе
id a c b
5556;57NULL
5656NULL
5757NULL
with My_CTE(PId, a, c, b, newC, inde) as
(
    select
        ST.PID, ST.a, ST.c, ST.b, res.C,
        ind = case 
	    when ST.a != '' 
                then (dense_rank() over(order by ST.a))
        end
    from STable as ST
    outer APPLY 
        fnSplit(ST.a) as res
    where (not(ST.a = '') or not(ST.c = ''))
)
UPDATE STable
Set b = 
cte.inde
From STable as st 
Join My_CTE as cte on st.PID = cte.PId;
GO 
Получаю на выходе следующее
id a c b
5556;5725
5656NULL
5757NULL

теперь нужно установить значения для дочерних записей по типу
id a c b
5556;57P25
565625
575725

как установить эти значения? в CTE или при Update? или отдельным Update (тогда как?)?
просто в CTE их сложно установить или я не могу додуматься как это сделать
26 июл 14, 06:53    [16360404]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
invm
Member

Откуда: Москва
Сообщений: 9683
_Novichok
как установить эти значения?
Ну можно примерно так:
declare @t table (id int, a varchar(100), c varchar(100), b varchar(100));

insert into @t
values
(55, '56;57', '', null),
(56, '', '56', null),
(57, '', '57', null);

with x as
(
 select
  t.id, null as parent_id, a.id_list,
  dense_rank() over (order by t.id) as r,
  cast('P' + cast(dense_rank() over (order by t.id) as varchar(10)) as varchar(100)) as cr
 from
  @t t cross apply
  (select cast('<x>' + replace(nullif(t.a, ''), ';', '</x><x>') + '</x>' as xml)) as a(id_list)

 union all

 select
  v.n.value('.[1]', 'int'), x.id, null, x.r, cast(x.r as varchar(100))
 from
  x cross apply
  x.id_list.nodes('/x') v(n)
)
update t
 set
  b = x.cr
from
 x join
 @t t on t.id = x.id
where
 x.id_list is not null or x.parent_id is not null;

select * from @t;
26 июл 14, 11:29    [16360577]     Ответить | Цитировать Сообщить модератору
 Re: Итерирование по строкам запроса  [new]
_Novichok
Member

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

если в таблицу добавить больше данных, то ваш скрипт будет работать неправильно:
declare @t table (id int, a varchar(100), c varchar(100), b varchar(100));

insert into @t
values
(55, '56;57', '', null),
(56, '', '56', null),
(57, '', '57', null),
(58, '59;60;61;62', '', null),
(59, '', '59', null),
(60, '', '60', null),
(61, '', '61', null),
(62, '', '62', null),
(63, '64', '', null),
(64, '', '64', null);


id a c b
5556;57P1
56561
57571
5859;60;61;62P4
59594
60604
61614
62624
6364P9
64649

а должно быть:
id a c b
5556;57P1
56561
57571
5859;60;61;62P2
59592
60602
61612
62622
6364P3
64643
28 июл 14, 02:13    [16364214]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить