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

Откуда:
Сообщений: 10
Здравствуйте уважаемые форумчане,
прошу помощи в создании запроса (запросов, процедур...) чтобы получилось следующее:

Имеется:

Time_Begin Time_End Group
116 06001
118 06020
122 14000
128 14000
132 14000
136 14000


Надо получить:

Time_Begin Time_End Group
116 117 06001
118 121 06020
122 14000
128 14000
132 14000
136 162 14000


Или лучше:

Time_Begin Time_End Group
116 117 06001
118 121 06020
122 162 14000


Здесь 162 ставится для последней строчки как максимально возможная дата.

Объект учета может менять группу учета, у меня есть код даты начала каждого периода,
все периоды идут последовательно.

Надо найти диапазоны дат для каждой группы.

Готов оплатить работу.

С уважением, Руслан
ruslun@gmail.ru
24 янв 12, 18:18    [11963099]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
iiyama
Member

Откуда:
Сообщений: 642
И не надо мне ни шоколада, ни мармелада
declare @t table (Time_Begin int, Time_End int, [Group] varchar(100)) 
declare @max_time int=162;

insert into @t(Time_Begin,[Group])values(116, '06001'),(118, '06020'),(122, '14000'),(128, '14000'),(132, '14000'),(136, '14000')

;with T as
(
 select ROW_NUMBER() over(order by Time_Begin) N, *
 from @t

)

select MIN(T1.Time_Begin), MAX(ISNULL(T2.Time_Begin-1, @max_time) ), T1.[Group] 
from T as T1 left join T T2 ON T1.N = T2.N-1
group by T1.[Group]
order by 3
24 янв 12, 18:55    [11963349]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
aleks2
Guest
iiyama
И не надо мне ни шоколада, ни мармелада


За халтуру мармелад не полагается.
declare @t table (Time_Begin int, Time_End int, [Group] varchar(100)) 
declare @max_time int=162;

insert into @t(Time_Begin,[Group])values(116, '06001'),(118, '06020'),(122, '14000'),(128, '14000'),(132, '14000'),(136, '14000')

;with 
T as
( select ROW_NUMBER() over(order by Time_Begin) N, * from @t)
,
TT as
(select T1.Time_Begin, T1.[Group], ROW_NUMBER() over(order by T1.Time_Begin) N 
from T as T1 left join T T2 ON T1.N-1 = T2.N 
WHERE T1.[Group]<>T2.[Group] or T2.[Group] is null
)
select T1.Time_Begin, ISNULL(T2.Time_Begin-1, 162) Time_End, T1.[Group] 
FROM TT T1 left join TT T2 ON T1.N+1 = T2.N 
24 янв 12, 19:20    [11963467]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
andrey odegov
Member

Откуда:
Сообщений: 473
"Я согласен на медаль." (c) А. Твардовский
declare @t table(Time_Begin int, Time_End int null, "Group" varchar(5));
declare @max_time int = 162;

insert into @t(Time_Begin, "Group")
values (116, '06001')
     , (117, '06001')
     , (118, '06020')
     , (120, '06020')
     , (122, '14000')
     , (128, '14000')
     , (132, '14000')
     , (136, '14000')
     , (138, '06001')
     , (145, '06001')
     , (150, '14000');

select min(Time_Begin) as Time_Begin
     , Time_End
     , "Group"
from (select l.Time_Begin
           , coalesce(min(r.Time_Begin) - 1, @max_time) as Time_End
           , l."Group"
      from @t as l left outer join @t as r
      on l."Group" != r."Group"
      and l.Time_Begin < r.Time_Begin
      group by l."Group", l.Time_Begin) as t
 group by "Group", Time_End
;
25 янв 12, 02:48    [11964799]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
Luniov Ruslan
Member

Откуда:
Сообщений: 10
Здравствуйте уважаемые программисты!
Благодарю за такой быстрый ответ с решением, только я слишком понадеялся на себя, дал сокращенную задачу,
а решить не смог. Мое предложение по вознаграждению остается в силе.

я попробовал применить ваше решение в своей задаче,
но знаний не хватает, согласитель ли вы помочь мне в конкретной задаче:

Имеется: Агент, Группа, Дата начала и дата окончания работы агента в группе.
StateChangeReason_Code: 0-начало работы, 1 - какие либо изменения, 2 - увольнение.

В результате должно получится так:
Агент, Группа, Дата начала, Дата окончания

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


В идеале должно получится:

(4508287617, '006007004', 102, 110, 1)
, (4508287617, '006013001', 111, 128, 2)


, (8001507237, '007006001', 116, 116, 0)
, (8001507237, '007006020', 117, 117, 1)
, (8001507237, '007014000', 118, 162, 1)


, (8004202649, '007006020', 119, 121, 0)
, (8004202649, '007014003', 122, 129, 2)

, (8004202649, '015025003', 132, 132, 0)

, (8004202649, '015025004', 133, 134, 2)


Исходные данные:

declare @t table(Agent_Code varchar(14), Group_cod varchar(9), ID_Time_Begin int, ID_Time_End int null, StateChangeReason_Code int)
declare @max_time int = 162

insert into @t(Agent_Code, Group_cod, ID_Time_Begin, ID_Time_End, StateChangeReason_Code)
values
(4508287617, '006007004', 102, Null, 0)
, (4508287617, '006007004', 110, Null, 1)

, (4508287617, '006013001', 111, Null, 1)
, (4508287617, '006013001', 118, Null, 1)
, (4508287617, '006013001', 128, Null, 1)
, (4508287617, '006013001', 128, 128, 2)



, (8001507237, '007006001', 116, Null, 0)

, (8001507237, '007006020', 117, Null, 1)

, (8001507237, '007014000', 118, Null, 1)
, (8001507237, '007014000', 120, Null, 1)
, (8001507237, '007014000', 122, Null, 1)
, (8001507237, '007014000', 128, Null, 1)
, (8001507237, '007014000', 132, Null, 1)
, (8001507237, '007014000', 136, Null, 1)


, (8004202649, '007006020', 119, Null, 0)

, (8004202649, '007014003', 122, Null, 1)
, (8004202649, '007014003', 128, Null, 1)
, (8004202649, '007014003', 129, 129, 2)

, (8004202649, '015025003', 132, Null, 0)

, (8004202649, '015025004', 133, Null, 1)
, (8004202649, '015025004', 134, 134, 2)

select l.Agent_Code
, l.Group_cod
, l.ID_Time_Begin
, coalesce(l.ID_Time_End, min(r.ID_Time_Begin) - 1, @max_time) as ID_Time_End

INTO #Nabor
from @t as l left outer join @t as r
on l.Agent_Code = r.Agent_Code
and l.Group_cod != r.Group_cod
and l.ID_Time_Begin < r.ID_Time_Begin
where l.StateChangeReason_Code = 1
group by l.Agent_Code, l.Group_cod, l.ID_Time_Begin, l.ID_Time_End

select Agent_Code
, Group_cod
, min(ID_Time_Begin) as ID_Time_Begin
, ID_Time_End
from #Nabor
group by Agent_Code, Group_cod, ID_Time_End
26 янв 12, 14:01    [11975581]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
aleks2
Guest
declare @t table(Agent_Code varchar(14), Group_cod varchar(9), ID_Time_Begin int, ID_Time_End int null, StateChangeReason_Code int)
declare @max_time int = 162

insert into @t(Agent_Code, Group_cod, ID_Time_Begin, ID_Time_End, StateChangeReason_Code)
values
  (4508287617, '006007004', 102, Null, 0)
, (4508287617, '006007004', 110, Null, 1)
, (4508287617, '006013001', 111, Null, 1)
, (4508287617, '006013001', 118, Null, 1)
, (4508287617, '006013001', 128, Null, 1)
, (4508287617, '006013001', 128, 128, 2)
, (8001507237, '007006001', 116, Null, 0)
, (8001507237, '007006020', 117, Null, 1)
, (8001507237, '007014000', 118, Null, 1)
, (8001507237, '007014000', 120, Null, 1)
, (8001507237, '007014000', 122, Null, 1)
, (8001507237, '007014000', 128, Null, 1)
, (8001507237, '007014000', 132, Null, 1)
, (8001507237, '007014000', 136, Null, 1)
, (8004202649, '007006020', 119, Null, 0)
, (8004202649, '007014003', 122, Null, 1)
, (8004202649, '007014003', 128, Null, 1)
, (8004202649, '007014003', 129, 129, 2)
, (8004202649, '015025003', 132, Null, 0)
, (8004202649, '015025004', 133, Null, 1)
, (8004202649, '015025004', 134, 134, 2)

;with 
T as
( select * 
     , ROW_NUMBER() over(partition by Agent_Code, Group_cod order by ID_Time_Begin ASC) N1 
     , ROW_NUMBER() over(partition by Agent_Code, Group_cod order by ID_Time_Begin DESC) N2
from @t)
,
B as (select * FROM T WHERE N1=1)
,
E as (select * FROM T WHERE N2=1)

select T1.Agent_Code, T1.Group_cod,  T1.ID_Time_Begin
       , ISNULL(T2.ID_Time_End, T2.ID_Time_Begin) ID_Time_End
FROM B T1 left outer join E T2 ON T1.Agent_Code=T2.Agent_Code AND T1.Group_cod = T2.Group_cod 
26 янв 12, 16:07    [11976991]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
andrey odegov
Member

Откуда:
Сообщений: 473
А сколько у Вас в таблице строк?
Может оказаться, что процедурный подход (курсор)
окажется предпочтительней по производительности.
Окончания выполнения запроса из моего предыдущего
решения я ждал 2 часа и прервал его. Объем тестовых
данных был 1000000 строк, сервер - чего-то на 4 ядрах
с 12 Гб памяти. Выполнению ничего больше не мешало.
set nocount on;
drop table #t;
create table #t( Agent_Code varchar(14)
               , Group_cod varchar(9)
               , ID_Time_Begin int
               , ID_Time_End int null
               , StateChangeReason_Code int );
declare @max_time int = 162;

insert into #t(Agent_Code, Group_cod, ID_Time_Begin, ID_Time_End, StateChangeReason_Code)
values (4508287617, '006007004', 102, Null, 0)
     , (4508287617, '006007004', 110, Null, 1)
     , (4508287617, '006013001', 111, Null, 1)
     , (4508287617, '006013001', 118, Null, 1)
     , (4508287617, '006013001', 128, Null, 1)
     , (4508287617, '006013001', 128, 128, 2)
     , (8001507237, '007006001', 116, Null, 0)
     , (8001507237, '007006020', 117, Null, 1)
     , (8001507237, '007014000', 118, Null, 1)
     , (8001507237, '007014000', 120, Null, 1)
     , (8001507237, '007014000', 122, Null, 1)
     , (8001507237, '007014000', 128, Null, 1)
     , (8001507237, '007014000', 132, Null, 1)
     , (8001507237, '007014000', 136, Null, 1)
     , (8004202649, '007006020', 119, Null, 0)
     , (8004202649, '007014003', 122, Null, 1)
     , (8004202649, '007014003', 128, Null, 1)
     , (8004202649, '007014003', 129, 129, 2)
     , (8004202649, '015025003', 132, Null, 0)
     , (8004202649, '015025004', 133, Null, 1)
     , (8004202649, '015025004', 134, 134, 2);

select Agent_Code
     , Group_cod
     , min(ID_Time_Begin) as ID_Time_Begin
     , case max(StateChangeReason_Code)
       when 2 then max(ID_Time_Begin)
       else coalesce(ID_Time_End, @max_time) end as ID_Time_End
     , max(StateChangeReason_Code) as StateChangeReason_Code
from (select l.Agent_Code
           , l.Group_cod
           , l.ID_Time_Begin
           , min(r.ID_Time_Begin) - 1 as ID_Time_End
           , max(l.StateChangeReason_Code) as StateChangeReason_Code
      from #t as l left outer join #t as r
      on l.Agent_Code = r.Agent_Code
      and l.Group_cod != r.Group_cod
      and l.ID_Time_Begin < r.ID_Time_Begin
      group by l.Agent_Code, l.Group_cod, l.ID_Time_Begin) as l
group by l.Agent_Code, l.Group_cod, l.ID_Time_End;
26 янв 12, 20:33    [11979242]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
andrey odegov
Окончания выполнения запроса из моего предыдущего
решения я ждал 2 часа и прервал его.

Группировка - операция дорогая, по возможности ее следует избегать.
26 янв 12, 20:43    [11979300]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
aleks2
Guest
Нада исправить свою халтуру

declare @t table(Agent_Code varchar(14), Group_cod varchar(9), ID_Time_Begin int, ID_Time_End int null, StateChangeReason_Code int)

insert into @t(Agent_Code, Group_cod, ID_Time_Begin, ID_Time_End, StateChangeReason_Code)
select 4508287617, '006007004', 102, Null, 0 union all
select 4508287617, '006007004', 110, Null, 1 union all
select 4508287617, '006013001', 111, Null, 1 union all
select 4508287617, '006013001', 118, Null, 1 union all
select 4508287617, '006013001', 128, Null, 1 union all
select 4508287617, '006013001', 128, 128, 2 union all
select 8001507237, '007006001', 116, Null, 0 union all
select 8001507237, '007006020', 117, Null, 1 union all
select 8001507237, '007014000', 118, Null, 1 union all
select 8001507237, '007014000', 120, Null, 1 union all
select 8001507237, '007014000', 122, Null, 1 union all
select 8001507237, '007014000', 128, Null, 1 union all
select 8001507237, '007014000', 132, Null, 1 union all
select 8001507237, '007014000', 136, Null, 1 union all
select 8004202649, '007006020', 119, Null, 0 union all
select 8004202649, '007014003', 122, Null, 1 union all
select 8004202649, '007014003', 128, Null, 1 union all
select 8004202649, '007014003', 129, 129, 2 union all
select 8004202649, '015025003', 132, Null, 0 union all
select 8004202649, '015025004', 133, Null, 1 union all
select 8004202649, '015025004', 134, 134, 2


;with 
T as
( select *, ROW_NUMBER() over(partition by Agent_Code order by ID_Time_Begin ASC) N from @t)
,
T1 as
(select T1.*, ROW_NUMBER() over(partition by T1.Agent_Code, T1.Group_cod order by T1.ID_Time_Begin) N1 
from T as T1 left join T T2 ON T1.Agent_Code=T2.Agent_Code AND T1.N-1=T2.N 
WHERE T1.Group_cod<>T2.Group_cod  or T2.Group_cod  is null
)
,
T2 as
(select T1.*, ROW_NUMBER() over(partition by T1.Agent_Code, T1.Group_cod order by T1.ID_Time_Begin) N1 
from T as T1 left join T T2 ON T1.Agent_Code=T2.Agent_Code AND T1.N+1=T2.N 
WHERE  T1.Group_cod<>T2.Group_cod or T2.Group_cod is null
)
select T1.Agent_Code, T1.Group_cod, T1.ID_Time_Begin, ISNULL(T2.ID_Time_Begin, T2.ID_Time_End) ID_Time_End
FROM T1 left join T2 ON T1.Agent_Code=T2.Agent_Code AND T1.Group_cod=T2.Group_cod AND T1.N1 = T2.N1 
27 янв 12, 05:55    [11980619]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
andrey odegov
Member

Откуда:
Сообщений: 473
kDnZP, я про индексы забыл
Создал - все стало хорошо :)
+
set nocount on;
use master;
if db_id(N'probe') is not null drop database probe;
create database probe;
go
use probe;
create table dbo.N(n int not null primary key clustered);
with a as (select c from (values (0), (0), (0), (0), (0), (0)
                               , (0), (0), (0), (0)) as a(c))
   , b as (select a.c from a as a/*, a as b*/)
   , t as (select row_number() over(order by (select 0)) as n
           from b as a, b as b, b as c)
insert into dbo.N select n from t;
create table dbo.T
( ac char(9) not null
, gc char(9) not null
, tb int not null check(tb > 0)
, te int null
, rc int not null check(rc between 0 and 2)
, check(te is null or (rc = 2 and te = tb)) );
alter table dbo.T add constraint pk_T primary key clustered (tb, gc, ac, rc);
create index T_ac_gc_tb on dbo.T(ac, gc, tb);
/*
use probe;
alter table dbo.T drop pk_T;
drop index dbo.T.T_ac_gc_tb;
*/
use master;
declare @q int, @i int, @c int = 1000000
      , @ac char(9), @gc char(9)
      , @rc int, @rc2 int, @tb int;
while @c > 0 begin
 set @ac = cast( 450000000
               + abs(checksum(newid()))
               % 450000000 as char(9) );
 set @i = 0
 while @c > 0 and @i < 3 begin
  set @q = abs(checksum(newid())) % case @i when 0 then 7 else 5 end;
  if @i < 2 set @q += 1;
  else if @q = 0 break;
  set @c -= @q;
  while 1 = 1 begin
   set @gc = right( '00'
                  + cast((select 6000000
                               + abs(checksum(newid()))
                               % 10000000) as varchar(9)), 9 );
   if not exists(select * from probe.dbo.T
                 where ac = @ac and gc = @gc and rc = 2) break;
  end;
  set @rc2 = case when abs(checksum(newid())) % 11 > 7 then 2 else 1 end;
  select @rc = max(rc), @tb = coalesce(max(tb), 100)
  from probe.dbo.T where ac = @ac and gc = @gc;
  if @rc is null set @rc = 0; else if @rc = 0 set @rc = 1;
  insert into probe.dbo.T(ac, gc, tb, te, rc)
  select @ac, @gc, @tb + n
       , case n
         when @q then case @rc2
                      when 2 then @tb + n
                      end
         end
       , case n
         when @q then @rc2
         when 1 then @rc
         else 1
         end
  from probe.dbo.N where n <= @q;
  set @i += 1;
 end;
end;
select ac, gc
     , min(tb) as tb
     , case max(rc)
       when 2 then max(tb)
       else coalesce(te, -1) end as te
     , max(rc) as rc
from (select l.ac, l.gc , l.tb
           , min(r.tb) - 1 as te
           , max(l.rc) as rc
      from probe.dbo.T as l left outer join probe.dbo.T as r
      on l.ac = r.ac and l.gc != r.gc and l.tb < r.tb
      group by l.ac, l.gc, l.tb) as l
group by l.ac, l.gc, l.te;
--if db_id(N'probe') is not null drop database probe;
27 янв 12, 12:53    [11982376]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
aleks2
Guest
andrey odegov
Создал - все стало хорошо

Осталось дождаться раздачи слонов тредстартером.
27 янв 12, 15:14    [11983954]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
Luniov Ruslan
Member

Откуда:
Сообщений: 10
Здравствуйте уважаемые форумчане!

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

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

Мое решение получилось такое:

/* Добавляю порядковые номера строк по всей таблице */
UPDATE tmp_RA_Period
SET Str_Num_Agent = Nabor.Numb
FROM
(Select Agent_Code, Group_cod, ID_Time_Begin, StateChangeReason_Code,
ROW_NUMBER() OVER(ORDER BY Agent_Code ASC, ID_Time_Begin ASC,
StateChangeReason_Code ASC) as Numb
FROM tmp_RA_Period) AS Nabor
INNER JOIN tmp_RA_Period ON
Nabor.Agent_Code = tmp_RA_Period.Agent_Code
AND Nabor.Group_cod = tmp_RA_Period.Group_cod
AND Nabor.ID_Time_Begin = tmp_RA_Period.ID_Time_Begin
AND Nabor.StateChangeReason_Code = tmp_RA_Period.StateChangeReason_Code
GO

UPDATE tmp_RA_Period
SET ID_Time_End = R.Time_End
FROM ( SELECT Agent_Code, Group_cod, ID_Time_Begin, Str_Num_Agent
FROM tmp_RA_Period
WHERE (ID_Time_End IS NULL)) AS L
INNER JOIN
( SELECT Agent_Code, Group_cod, ID_Time_Begin, ID_Time_Begin - 1 as Time_End, Str_Num_Agent
FROM tmp_RA_Period ) AS R
ON L.Agent_Code = R.Agent_Code AND L.Str_Num_Agent = R.Str_Num_Agent - 1

INNER JOIN
tmp_RA_Period ON
L.ID_Time_Begin = tmp_RA_Period.ID_Time_Begin
AND L.Group_cod = tmp_RA_Period.Group_cod
AND L.Agent_Code = tmp_RA_Period.Agent_Code
GO

Вот этот вариант у меня работает как надо, допускаю, что по коду он не оптимальный.

Я делаю большую систему: база данных генерится на основании выгрузок из 1С, сейчас мне надо делать отчеты по полученным данным и развивать аналитику.

Если кто готов поучаствовать в разработке интерактивных отчетов- сообщите.
9 фев 12, 11:40    [12060454]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
aleks2
Guest
1. Опять обещают розовых слонов.
2. Нахера разбираться в этом элементарном бреде?
9 фев 12, 12:32    [12061038]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
Luniov Ruslan
Member

Откуда:
Сообщений: 10
А я и не отказываюсь от раздачи слонов,
я предложил задачу и сообщил о материальной заинтересованности,
решение задачи было предложено, про слонов никто не спросил.

Мне нужен специалист для решения моих задач, за это я готов заплатить, что то никто не желает сообщить о намерениях.

С уважением, Лунёв Руслан
9 фев 12, 12:42    [12061155]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
aleks2
Guest
1. Вот нахера там JOIN в первом update?

declare @t table(n int, s char)

insert @t(s) select 'a'
insert @t(s) select 'b'

update T set n=T.m
FROM 
(select *, ROW_NUMBER() OVER(order by s) m FROM @t) T

select * from @t


2. Я уж молчу о том, что название tmp_RA_Period кагбе намекает на временную таблицу, заполняемую специально под указанное действо... И чо бы не использовать IDENTITY прям при заполнении tmp_RA_Period?
9 фев 12, 12:44    [12061184]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в написании процедуры (за вознаграждение)  [new]
Luniov Ruslan
Member

Откуда:
Сообщений: 10
Не надо волноваться,
tmp в названии таблицы правильно говорит о ее временности,
только там большая серия обновлений, не связанных с этой задачей,
поэтому сначала я делаю все во временной таблице, а из нее накатываю на боевую,
обработка выгрузки из 1С занимает полчаса, а накатывание на боевую базу - меньше минуты.

Ну а зачем там лишний оператор, ну так получилось у меня, в данном случае главное - получилось,
оптимизировать потом буду.

Вот бы мне кто помог с отчетами, я посмотрел на возможности Reporting и огорчился,
похоже удобные интерактивные отчеты там сложно делать.
9 фев 12, 17:43    [12064869]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить