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

Откуда:
Сообщений: 60
Есть четыре таблицы
create table one(
id_1 int identity,
count int not null
)
create table second(
id_2 int identity,
tema varchar(50) not null
)
create table third(
id int identity,
id_2 int not null,
id_1 int not null
)
create table firth(
id_4 int identity,
id int not null,
date datetime null
)
А это запрос
declare @id_2 int;
declare @id_1 int;
select o.count - (select count(f.id) from firth f
inner join third t2
on f.id = t2.id
where f.date is null and t2.id_2 = @id_2
and t2.id_1 = @id_1)
from one o
inner join third t
on o.id_1 = t.id_1
where t.id_2 = @id_2
and t.id_1 = @id_1
11 ноя 09, 23:10    [7917249]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли оптимизировать запрос  [new]
Андрей Ю.
Member

Откуда:
Сообщений: 60
declare @id_2 int;
declare @id_1 int;
select o.count - (select count(f.id) from firth f
inner join third t2
on f.id = t2.id
where f.date is null and t2.id_2 = @id_2
and t2.id_1 = @id_1)
from one o
inner join third t
on o.id_1 = t.id_1
where t.id_2 = @id_2
and t.id_1 = @id_1

учусь писать красиво :)
11 ноя 09, 23:19    [7917287]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли оптимизировать запрос  [new]
iljy
Member

Откуда:
Сообщений: 8711
Андрей Ю.,

Не знаю, что вы хотели получить, но получите странное. Похоже что рассчитываете получить одну запись, а получите одну, но несколько раз, а именно - столько, сколько записей с id_2 = @id_2 and id_1 = @id_1 есть в таблице third. Попробуйте так
select o.count - (select count(f.id) from firth f
                        inner join third t2
                        on f.id = t2.id
                        where f.date is null and t2.id_2 = @id_2
                        and t2.id_1 = @id_1)
from one o
where o.id_1 = @id_1 and exists
(select * from third t
where t.id_2 = @id_2
and t.id_1 = @id_1
)
дальше можно поизвращаться с оптимизацией, например так
select o.count - t.f_null
from one o cross join
  (select count(*) total, count(case when f.date is null then 1 end) f_null
   from firth f inner join third t2 on f.id = t2.id
   where t.id_2 = @id_2 and t.id_1 = @id_1
  ) t
where o.id_1 = @id_1 and t.total > 0
12 ноя 09, 00:16    [7917458]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли оптимизировать запрос  [new]
Андрей Ю.
Member

Откуда:
Сообщений: 60
iljy,
я условие закрутил так, что возвращается одна запись, но вижу, что перемудрил, за наставления большое спасибо
12 ноя 09, 00:34    [7917487]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли оптимизировать запрос  [new]
iljy
Member

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

в смысле - одна? Вот данные, пробуйте!
insert into one (count) values(2),(3),(4)
insert into third(id_1,id_2) values(2,1),(3,2),(2,3),(2,1)
insert into firth(id,date) values(1,null),(1,'19000101'),(2,null)
это для 2008, если меньше - надо заменить так
insert into one (count) select 2 union all select 3 union all select 4
12 ноя 09, 00:44    [7917505]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли оптимизировать запрос  [new]
Андрей Ю.
Member

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

когда вставляются данные, то происходит запрет на добавление существующих и т.д. , 
говорю ж такого намудрил, ну и в результате происходит только выборка одного значения.
Поэтому спрашиваю как его оптимизировать дабы перестроить все таблицы и условия 
12 ноя 09, 00:52    [7917513]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли оптимизировать запрос  [new]
iljy
Member

Откуда:
Сообщений: 8711
Андрей Ю.
iljy,

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

Чего намудрили-то? Запрет дубликатов делается созданием уникального индекса по нужным полям. В вашем случае видимо по (id_1, id_2). И запрос побыстрее работать будет.
12 ноя 09, 01:00    [7917527]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли оптимизировать запрос  [new]
Андрей Ю.
Member

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

это собственно процедура в которой происходит вставка данных в укороченную таблицу firth
-- 
create procedure spAddBookRead
(
  @id_b int, -- номер карточки книги
  @id_p int, -- номер карточки посетителя
  @id_d int, -- id киги
  @id_biblitekar int,

  @vidana datetime,

  @error_message varchar(200) output
)
--WITH RECOMPILE
as
begin
  if (select kp.ZakritAbonement
     from KartotekaPosetiteley kp
     where kp.NumberKartochkiPos = @id_p) is not null
  begin
     set @error_message = 'Абонемент закрыт';
     return 13;
  end
  if exists (select br.id from BookRead br
             inner join KartDannieBook kdb
             on br.id = kdb.id
             where kdb.NumberKartochkiBook = @id_b and
                   br.NumberKartochkiPos = @id_p and
                   br.vozvrashena is null)
  begin
   set @error_message = 'Данный экземпляр книги уже выдан посетителю.';
   return 13;
  end
     
  set xact_abort on;
  declare @kol_book_vnalichii int; -- количество книг в наличии(свободных для выдачи)
  declare @kol_razr_nevoz int; -- количество разрешенных книг к невозвращению
  declare @xact_state int;
  declare @id int; -- KartDannieBook table

  set @kol_book_vnalichii = dbo.fnCountBookVnalichii( @id_b, @id_d );[b]в этой функции выполняется тот самый запрос[/b]
  select @kol_razr_nevoz = dbo.fnCountBookIntoPosetitel ( @id_p );
  select @id = id from KartDannieBook kdb where kdb.NumberKartochkiBook = @id_b
                                          and kdb.id_dannie = @id_d
 
  if @kol_book_vnalichii > 0 and @kol_razr_nevoz > 0
   begin
     begin try
       begin tran add_book_read
         -- вставляем данные в таблицу выдачи книг
         insert into BookRead
         values ( @id_p, @id_biblitekar, @id, @vidana, null, null);
       commit tran add_book_read
     end try
     begin catch
       set @xact_state = XACT_STATE()
       if @xact_state = -1
       begin
         set @error_message = ERROR_MESSAGE();
         rollback tran add_book_read;
         return -1;
       end;
     end catch
   end
  else
    begin
       if @kol_razr_nevoz <= 0
         begin
           set @error_message = 'Посетителем исчерпан лимит на получение книг - '+ cast(@kol_razr_nevoz as varchar)
           return 13
         end
       if @kol_book_vnalichii <= 0
         begin
           set @error_message = 'Свободных дааной книги нет - ' + cast(@kol_book_vnalichii as varchar)
           return 13
         end
    end
end
почему возвращает одно значение сам не пойму, но возвращает
12 ноя 09, 01:10    [7917538]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли оптимизировать запрос  [new]
Андрей Ю.
Member

Откуда:
Сообщений: 60
[/quot]
Чего намудрили-то? Запрет дубликатов делается созданием уникального индекса по нужным полям. В вашем случае видимо по (id_1, id_2). И запрос побыстрее работать будет.[/quot]
Я понял почему пока выбирается только одна запись и не возникает ошибки, у меня в таблице  third есть только такие даннные
1 1 1
2 1 2
, а следовательно нодо запретить дублирование третьего столбца, так как этого не должно быть
, спасибо еще раз . Тема закрыта.
12 ноя 09, 01:44    [7917563]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли оптимизировать запрос  [new]
Анонимус
Guest
Андрей Ю.

begin tran add_book_read
-- вставляем данные в таблицу выдачи книг
insert into BookRead
values ( @id_p, @id_biblitekar, @id, @vidana, null, null);
commit tran add_book_read

ГЫЫЫЫ.....

Начни оптимизацию не с запроса, а с головы
12 ноя 09, 06:52    [7917681]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить