оцените процедуру, пожалуйста

koJIo6ok
Дата: 21.01.2009 16:28:20
есть у меня вот такая процедура, я ток учусь SQL так мне вот интересно так как я сделал это нормально или так не делаться?
меня смущает что много временных таблиц и в итоговом select-e много join-ов получается или это нормально?
create proc general.usp_derevo_fin_po_ob
	--исходные параметры
			@mes_tek		tinyint,
			@god_tek		smallint
as
begin
set nocount on
	--вычисляемые параметры
declare		@first_day_tm	smalldatetime	--первый день из @god_tek и @mes_tek
declare		@last_day_tm	smalldatetime	--последний день из @god_tek и @mes_tek
declare		@first_day_pm	smalldatetime	--первый день пред месяца
declare		@last_day_pm	smalldatetime	--последний день пред месяца
declare		@first_day_tg	smalldatetime	--первый день тек года
declare		@mes_pred	tinyint		--пред месяц
declare		@god_mes_pred	smallint		--год пред месяца
declare		@mes_sled	tinyint		--след месяц
declare		@god_mes_sled	smallint		--год след месяц
	--зад знач парам
set @first_day_tm = prog.DateSerial(@god_tek, @mes_tek, 1)
set @last_day_tm = prog.DateSerial(@god_tek, @mes_tek + 1, 0)
set @first_day_pm = prog.DateSerial(@god_tek, @mes_tek - 1, 1)
set @last_day_pm = prog.DateSerial(@god_tek, @mes_tek , 0)
set @first_day_tg = prog.DateSerial(@god_tek, 1 , 1)
set @mes_pred = month(@first_day_pm)
set @god_mes_pred = year(@first_day_pm)
set @mes_sled = month(prog.DateSerial(@god_tek, @mes_tek + 1, 1))
set @god_mes_sled = year(prog.DateSerial(@god_tek, @mes_tek + 1, 1))
	
-- 2 - сальдо
declare @saldo table
(id_ob	int		null,
 saldo	decimal(15,3)	null)

insert into @saldo( id_ob, saldo )
select id_ob, saldo
from pldo_fin.ob_saldo_ng
where god = @god_tek				--текущий год
-- 3 - к оплате нарастающим
declare @k_opl_n table
(id_ob		int		null,
 k_opl_nar	decimal(15,3)	null)

insert into @k_opl_n(id_ob, k_opl_nar)
select oo.id_ob, sum(vip.fakt_dc_okv - vip.vozvrat_vr)
from pldo_vip.object as ob
inner join pldo_vip.org_ob as oo
on ob.id_ob = oo.id_ob
inner join pldo_vip.plg_org as plg
on oo.id_org_ob = plg.id_org_ob and plg.god = @god_tek		-- текущий год
inner join pldo_vip.vipoln as vip
on plg.id_plg = vip.id_plg and vip.kod_mes < @mes_tek	    -- текущий месяц
group by oo.id_ob
-- 4 - к оплате за месяц
declare @k_opl_tm table
(id_ob			int		null,
 k_opl_tm		decimal(15,3)	null)

insert into @k_opl_tm(id_ob, k_opl_tm)
select oo.id_ob, sum(vip.fakt_dc_okv - vip.vozvrat_vr)
from pldo_vip.object as ob
inner join pldo_vip.org_ob as oo
on ob.id_ob = oo.id_ob
inner join pldo_vip.plg_org as plg
on oo.id_org_ob = plg.id_org_ob and plg.god = @god_mes_pred		-- год зависит от месяца
inner join pldo_vip.vipoln as vip
on plg.id_plg = vip.id_plg and vip.kod_mes = @mes_pred			-- предыдущий месяц
group by oo.id_ob
-- 5 - оплачено пред месяц
declare @opl_pred_mes table
(id_ob		int		null,
 opl_pred_mes	decimal(15,3)	null);

insert into @opl_pred_mes(id_ob, opl_pred_mes)
select id_ob, sum(summa) 
from buh.oborot_den_sr
where (kod_np = 1 and kod_t = 1 and  data between @first_day_pm and @last_day_pm) or (kod_t = 2 and data between @first_day_pm and @last_day_pm) --оплачено за выполн работы
group by id_ob								--первый день и последний день пред месяца					
-- 6,7 - зачтено  авансов пред месяц
declare @az_pred_mes table
(id_ob		int		null,
 ta_z_pr_mes	decimal(15,3)	null,
 ca_z_pr_mes	decimal(15,3)	null,
 ind_pr_mes	decimal(15,3)	null)

insert into @az_pred_mes(id_ob, ta_z_pr_mes, ca_z_pr_mes, ind_pr_mes)
select id_ob, tek_av_z, cel_av_z, indeks
from pldo_fin.ob_avans_zachet
where god = @god_mes_pred and kod_mes = @mes_pred -- год зависит от месяца --предыдущий месяц
-- 8 - зачтено  материалов пред месяц
declare @mz_pred_mes table
(id_ob		int		null,
 mz_pred_mes	decimal(15,3)	null)

insert into @mz_pred_mes(id_ob, mz_pred_mes)
select id_ob, mat_dor_z + mat_bel_z + mat_pr_z 
from pldo_fin.ob_mat_zachet
where god = @god_mes_pred and kod_mes = @mes_pred  -- год зависит от месяца --предыдущий месяц
--  оплачено на начало месяца
declare @opl_na_nm table
(id_ob		int		null,
 opl_na_nm	decimal(15,3)	null)

insert into @opl_na_nm(id_ob, opl_na_nm)
select id_ob, sum(summa)
from buh.oborot_den_sr
where (kod_np = 1 and kod_t = 1 and  data between @first_day_tg and @last_day_pm) or (kod_t = 2 and data between @first_day_tg and @last_day_pm) --оплачено за выполн работы
group by id_ob									--с начала года по последний день пред месяца
--  зачтено авансов на начало месяца
declare @az_na_nm table
(id_ob		int		null,
 az_na_nm	decimal(15,3)	null)

insert into @az_na_nm(id_ob, az_na_nm)
select id_ob, sum(tek_av_z + cel_av_z + indeks)
from pldo_fin.ob_avans_zachet
where god = @god_tek and kod_mes < @mes_tek --тек год тек месяц
group by id_ob
--  зачтено материалов на начало месяца
declare @mz_na_nm table
(id_ob		int		null,
 mz_na_nm	decimal(15,3)	null)

insert into @mz_na_nm(id_ob, mz_na_nm)
select id_ob, sum(mat_dor_z + mat_bel_z + mat_pr_z )
from pldo_fin.ob_mat_zachet
where god = @god_tek and kod_mes < @mes_tek --тек год тек месяц
group by id_ob
-- 10 - оплачено за тек месяц
declare @opl_tm table
(id_ob		int		null,
 opl_tm		decimal(15,3)	null)

insert into @opl_tm(id_ob, opl_tm)
select id_ob, sum(summa)
from buh.oborot_den_sr
where (kod_np = 1 and kod_t = 1 and  data between @first_day_tm and @last_day_tm) or (kod_t = 2 and data between @first_day_tm and @last_day_tm) --оплачено за выполн работы
group by id_ob									--первый день тек месяца по посл день тек месяца
-- 13 - пост тек авансов на след мес
declare @tek table
(id_ob		int		null,
 tek_av_post	decimal(15,3)	null)

insert into @tek(id_ob, tek_av_post)
select id_ob, sum(summa)
from buh.oborot_den_sr
where kod_np = 2 and god = @god_mes_sled and kod_mes = @mes_sled and kod_t = 1 -- след месяц, год от месяца
group by id_ob;
-- 15 - пост цел авансов в этом месяце
declare @cel table
(id_ob		int		null,
 cel_av_post	decimal(15,3)	null)

insert into @cel(id_ob, cel_av_post)
select id_ob, sum(summa)
from buh.oborot_den_sr
where kod_np = 3 and kod_t = 1 and data between @first_day_tm and @last_day_tm  --первый день тек месяца по посл день тек месяца
group by id_ob;

select nif.kod_if, nif.nazv_if, nz.nazv_org, ob.nazv_ob, nf.nazv_fil, saldo, k_opl_nar, k_opl_tm, 
case isnull(opl_pred_mes,0) + isnull(ta_z_pr_mes,0) + isnull(ca_z_pr_mes,0) + isnull(ind_pr_mes,0) + isnull(mz_pred_mes,0) 
when 0 then null
else isnull(opl_pred_mes,0) + isnull(ta_z_pr_mes,0) + isnull(ca_z_pr_mes,0) + isnull(ind_pr_mes,0) + isnull(mz_pred_mes,0)
end as 'itogo_opl_pred_mes',
ta_z_pr_mes, ca_z_pr_mes , mz_pred_mes,
case isnull(saldo,0) + isnull(k_opl_nar,0) - isnull(opl_na_nm,0) - isnull(az_na_nm,0) - isnull(mz_na_nm,0)
when 0 then null
else isnull(saldo,0) + isnull(k_opl_nar,0) - isnull(opl_na_nm,0) - isnull(az_na_nm,0) - isnull(mz_na_nm,0)
end as 'zad_na_nm',
opl_tm,
case isnull(saldo,0) + isnull(k_opl_nar,0) - isnull(opl_na_nm,0) - isnull(az_na_nm,0) - isnull(mz_na_nm,0) - isnull(opl_tm,0)
when 0 then null
else isnull(saldo,0) + isnull(k_opl_nar,0) - isnull(opl_na_nm,0) - isnull(az_na_nm,0) - isnull(mz_na_nm,0) - isnull(opl_tm,0)
end as 'zad_na_tek_d',
atp.tek_av_p as 'tek_av_plan', tek_av_post, aсp.cel_av_p as 'cel_av_plan', cel_av_post, prim
from pldo_vip.object as ob
inner join nw.n_if as nif
on ob.kod_if = nif.kod_if
inner join general.org as nz
on ob.id_zak = nz.id_org and nz.id_org > 1
inner join nw.n_fil as nf
on ob.kod_fil = nf.kod_fil
left join @saldo as saldo
on ob.id_ob = saldo.id_ob
left join @k_opl_n as k_opl_n
on ob.id_ob = k_opl_n.id_ob
left join @k_opl_tm as k_opl_tm
on ob.id_ob = k_opl_tm.id_ob
--пред мес
left join @opl_pred_mes as opl_pred_mes
on ob.id_ob = opl_pred_mes.id_ob
left join @az_pred_mes as az_pred_mes
on ob.id_ob = az_pred_mes.id_ob
left join @mz_pred_mes as mz_pred_mes
on ob.id_ob = mz_pred_mes.id_ob
--нар
left join @opl_na_nm as opl_na_nm
on ob.id_ob = opl_na_nm.id_ob
left join @az_na_nm as az_na_nm
on ob.id_ob = az_na_nm.id_ob
left join @mz_na_nm as mz_na_nm
on ob.id_ob = mz_na_nm.id_ob
--tm
left join @opl_tm as opl_tm
on ob.id_ob = opl_tm.id_ob
--plan av
left join pldo_fin.ob_avans_plan as atp
on ob.id_ob = atp.id_ob and atp.god = 2009 and atp.kod_mes = 2 --год от месяца след мес
left join pldo_fin.ob_avans_plan as aсp
on ob.id_ob = aсp.id_ob and aсp.god = 2009 and aсp.kod_mes = 1 --тек год тек месяц
left join @tek as tek
on ob.id_ob = tek.id_ob
left join @cel as cel
on ob.id_ob = cel.id_ob
--prim
left join pldo_fin.prim_fin as pr
on ob.id_ob = pr.id_ob
--where задолженность на начало мес не равна 0, или поступившие/планируемые авансы не равны 0
where (ob.id_ob <> 1 and ob.kod_if <> 200 and (isnull(saldo,0) + isnull(k_opl_nar,0) - isnull(opl_na_nm,0) - isnull(az_na_nm,0) - isnull(mz_na_nm,0)) <> 0)
or (ob.id_ob <> 1 and ob.kod_if <> 200 and atp.tek_av_p <> 0)
or (ob.id_ob <> 1 and ob.kod_if <> 200 and tek_av_post <> 0)
or (ob.id_ob <> 1 and ob.kod_if <> 200 and aсp.cel_av_p <> 0)
or (ob.id_ob <> 1 and ob.kod_if <> 200 and cel_av_post <> 0)
order by kod_if, nazv_org, nazv_ob
end;

зы Microsoft SQL Server 2005 - 9.00.3239.00 (Intel X86) Apr 9 2008 22:56:02
сервер - Intel Xeon 5420 два штуки, 8 гб ОЗУ, HDD(10 шт) - raid1 - OS+MsSql-сервер, raid1 - всяка ерунда, raid50 + данные и логи БД
Паганель
Дата: 21.01.2009 16:39:24
Я думаю так:
1) При возможности побейте на части (Inline table-valued functions, например...)
2) Отформатируйте и откомментируйте по максимуму

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

ЗЫ А почему константа 2009? Что будет с процедурой в 2010 году?
ЗЗЫ И где тут временные таблицы?
Glory
Дата: 21.01.2009 16:40:57
koJIo6ok
есть у меня вот такая процедура, я ток учусь SQL так мне вот интересно так как я сделал это нормально или так не делаться?
меня смущает что много временных таблиц и в итоговом select-e много join-ов получается или это нормально?

Смущает чем ? Производительностью ? Или просто наличием ?
koJIo6ok
Дата: 21.01.2009 16:44:40
Паганель
Я думаю так:
1) При возможности побейте на части (Inline table-valued functions, например...)
2) Отформатируйте и откомментируйте по максимуму

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

ЗЫ А почему константа 2009? Что будет с процедурой в 2010 году?
ЗЗЫ И где тут временные таблицы?


(Inline table-valued functions, например...) - а что это такое?
2009 не заменил на переменную - забыл я...
ну declare @saldo table - это не временные таблицы?
koJIo6ok
Дата: 21.01.2009 16:48:06
Glory
koJIo6ok
есть у меня вот такая процедура, я ток учусь SQL так мне вот интересно так как я сделал это нормально или так не делаться?
меня смущает что много временных таблиц и в итоговом select-e много join-ов получается или это нормально?

Смущает чем ? Производительностью ? Или просто наличием ?

да не сервер не старый данных нет почти - работает быстро за 00:00:00
мне интересно так как я сделал это нормально или нет? создал временные таблицы - в них данные вставил потом выбрал что надо в итоговый запрос?
Glory
Дата: 21.01.2009 16:50:36
koJIo6ok
Glory
koJIo6ok
есть у меня вот такая процедура, я ток учусь SQL так мне вот интересно так как я сделал это нормально или так не делаться?
меня смущает что много временных таблиц и в итоговом select-e много join-ов получается или это нормально?

Смущает чем ? Производительностью ? Или просто наличием ?

да не сервер не старый данных нет почти - работает быстро за 00:00:00
мне интересно так как я сделал это нормально или нет? создал временные таблицы - в них данные вставил потом выбрал что надо в итоговый запрос?

Т.е. вы хотите, чтобы по предложенному коду оценили, как хорошо вы решили неизвестную задачу на неизвестной структуре ?
Почему, например, у ваших табличных переменных нет ПК ? Вы противник индексов ?
koJIo6ok
Дата: 21.01.2009 16:57:29
Glory
koJIo6ok
Glory
koJIo6ok
есть у меня вот такая процедура, я ток учусь SQL так мне вот интересно так как я сделал это нормально или так не делаться?
меня смущает что много временных таблиц и в итоговом select-e много join-ов получается или это нормально?

Смущает чем ? Производительностью ? Или просто наличием ?

да не сервер не старый данных нет почти - работает быстро за 00:00:00
мне интересно так как я сделал это нормально или нет? создал временные таблицы - в них данные вставил потом выбрал что надо в итоговый запрос?

Т.е. вы хотите, чтобы по предложенному коду оценили, как хорошо вы решили неизвестную задачу на неизвестной структуре ?
Почему, например, у ваших табличных переменных нет ПК ? Вы противник индексов ?

да нет само решение оценить - табличные переменные - в них данные - потом итоговый селект
а я не знал просто што ПК можно создавать у табличных переменных
koJIo6ok
Дата: 21.01.2009 17:00:56
declare @saldo table
(id_ob	int		not null primary key clustered,
 saldo	decimal(15,3)	null)
точно оказывается можно, вот видите не зря спросил - уже будет получше
спасибо может еще что?
--__Александр__--
Дата: 21.01.2009 17:51:45
Ну вообще важно понимать, когда лучше использовать временные таблицы(#), а когда табличные переменнеы(@). Да и не факт, что здесь ПК нужен на эти таблицы.
А делать можно как угодно, главное - что бы работало быстро.