Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Оборотная ведомость / 7 сообщений из 7, страница 1 из 1
23.06.2001, 08:39
    #32008194
kindzer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оборотная ведомость
Кто нибудь пробовал написать оборотную ведомость (бухгалтерия)
а то у меня, что то не красиво получается

CREATE PROCEDURE Buh_Оборотка
@n1 datetime, @n2 datetime, @userid int
AS

set nocount on
delete from M__ТаблицаДляОтчетов where USER_UID=@userid

insert into M__ТаблицаДляОтчетов( USER_UID, cField1, cField2, nField1, nField2, nField3, nField4, nField5, nField6)
select @userid, COD, NAMES, isnull(sum(nSD),0) nSD,
isnull(sum(nSK),0) nSK,
isnull(sum(OD),0) OD,
isnull(sum(OK),0) OK,
isnull(sum(kSD),0) kSD,
isnull(sum(kSK),0) kSK
from M__PLAN p left join (
select SMK, dbo.BuhSaldoD( SDn, IN_ACTIV, IN_PASSIV) nSD, -- Сальдо дебет
dbo.BuhSaldoK( -SDn, IN_ACTIV, IN_PASSIV) nSK, -- Сальдо кредит
OD, -- Оборот дебет
OK, -- Оборот кредит
dbo.BuhSaldoD( SDk, IN_ACTIV, IN_PASSIV) kSD, -- Сальдо кредит
dbo.BuhSaldoK( -SDk, IN_ACTIV, IN_PASSIV) kSK -- Сальдо кредит
from (
select SMK, sum(SD)-sum(SK) as SDn, sum(OD) as OD, sum(OK) as OK,
sum(SD)-sum(SK)+sum(OD)-sum(OK) SDk
from (
-- Сальдо дебет на начало
select SMKD "SMK", SUMD SD, 0 SK, 0 OD, 0 OK
from B_ЖурналПроводок
where OPER_ID in (select OPER_UID from B_ЖурналОпераций where OPER_DATE < @n1)
union all
-- Сальдо кредит на начало
select SMKK "SMK", 0 SD, SUMD SK, 0 OD, 0 OK
from B_ЖурналПроводок
where OPER_ID in (select OPER_UID from B_ЖурналОпераций where OPER_DATE < @n1)
union all
-- Оборот по дебету
select SMKD "SMK", 0 SD, 0 SK, SUMD OD, 0 OK
from B_ЖурналПроводок
where OPER_ID in (select OPER_UID from B_ЖурналОпераций where
OPER_DATE between @n1 and @n2)
union all
-- Оборот по кредиту
select SMKK "SMK", 0 SD, 0 SK, 0 OD, SUMD SK
from B_ЖурналПроводок
where OPER_ID in (select OPER_UID from B_ЖурналОпераций where
OPER_DATE between @n1 and @n2)
) x group by SMK
) y left join M__PLAN p on p.COD=y.SMK
where (IN_ACTIV=1 or IN_PASSIV=1) and rtrim(SMK)<>'00'
) ob on ob.SMK like rtrim(p.COD)+'%'
where nSD<>0 or nSK<>0 or OD<>0 or OK<>0 or kSD<>0 or kSK<>0
group by COD, NAMES
order by COD
...
Рейтинг: 0 / 0
25.06.2001, 06:07
    #32008222
SergSuper
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оборотная ведомость
Ну я например так написал, тоже наверное не шедевр. Будете разбираться? (Я например Ваше творчество не стал смотреть, не потому что плохо или непонятно написано - ну лень разбираться, до и своё время ценю немного.)
Единственно что посоветовал бы - не старайтесь делать всё в одном запросе.

\ncreate procedure p_osv
@bln varchar(10),
@fond varchar(20),
@date1 datetime,
@date2 datetime
AS
BEGIN
declare @z999 varchar(30)
set nocount on
select @z999='99999999999'
create table #p(
acc varchar(30),
si dec(19,6),
d dec(19,6),
c dec(19,6),
so dec(19,6))
create table #t(
t int,
acc varchar(30) null,
sub varchar(30) null,
num varchar(30) null,
name varchar(300) null,
type int null,
si dec(19,6) null,
ai dec(19,6) null,
pi dec(19,6) null,
d dec(19,6) null,
c dec(19,6) null,
so dec(19,6) null,
ao dec(19,6) null,
po dec(19,6) null,
cnt int null)
--- t ---
-- 10 - состояние лицевого счета
-- 20 - состояния субсчета
-- 30 - состояния б.счета
select acc, max(date) d
into #d from AccState (nolock)
where bln=@bln and fond=@fond and date<@date1
group by acc

insert #p
select d.acc, s,0,0, s
from #d d, AccState s(nolock)
where d.acc=s.acc and d=date
and bln=@bln and fond=@fond

insert #p
select acc, 0, dt, cr, dt-cr
from AccState s(nolock)
where date between @date1 and @date2
and bln=@bln and fond=@fond

insert #t(t,acc,si,d,c,so)
select 10, acc, sum(si), sum(d), sum(c), sum(so)
from #p
group by acc


update #t
set type=a.type, name=a.name, sub=a.sub
from #t t, Acc a
where t.acc=a.acc
and bln=@bln and fond=@fond

update #t
set ai= case when (type=1) or (type=3 and si>0) then si else 0 end,
pi= case when (type=2) or (type=3 and si<0) then -si else 0 end,
ao= case when (type=1) or (type=3 and so>0) then so else 0 end,
po= case when (type=2) or (type=3 and so<0) then -so else 0 end

insert #t(t, sub, acc, ai,pi, d,c, ao,po)
select 20,sub,@z999,sum(ai),sum(pi),sum(d),sum(c),sum(ao),sum(po)
from #t
where t=10
group by sub

update #t
set type=a.type, name=a.name, num=a.num
from #t t, PlnSub a
where t=20 and a.sub=t.sub
and bln=@bln

update #t
set num=a.num
from #t t, PlnSub a
where t=10 and a.sub=t.sub
and bln=@bln

insert #t(t, num, sub, acc, ai,pi, d,c, ao,po)
select 30, num,@z999,@z999,sum(ai),sum(pi),sum(d),sum(c),sum(ao),sum(po)
from #t
where t=20
group by num

update #t
set name=n.name
from #t t, PlnNum n
where t=30 and n.num=t.num
and bln=@bln

insert #t(t,num,sub,acc,name)
select -t, num, case when t=20 then sub else '' end,'', name
from #t
where t in (20,30)

select sub ss, count(*) c
into #t20 from #t
where t=10
group by sub

update #t
set cnt=c.c
from #t20 c
where t=-20 and ss=sub

select num n, count(*) c2, sum(cnt) c
into #t30 from #t
where t=-20
group by num

update #t
set cnt=c.c+c2*2
from #t30 c
where t=-30 and n=num

set nocount off

select
t ,
acc ,
sub ,
num ,
name ,
type ,

case @bln when 'D' then convert(varchar(20),convert(int,ai))
when 'M' then convert(varchar(20),convert(money,ai))
when 'P' then convert(varchar(20),ai)
else '***' end ai,
case @bln when 'D' then convert(varchar(20),convert(int,pi))
when 'M' then convert(varchar(20),convert(money,pi))
when 'P' then convert(varchar(20),pi)
else '***' end pi,
case @bln when 'D' then convert(varchar(20),convert(int,d))
when 'M' then convert(varchar(20),convert(money,d))
when 'P' then convert(varchar(20),d)
else '***' end d,
case @bln when 'D' then convert(varchar(20),convert(int,c))
when 'M' then convert(varchar(20),convert(money,c))
when 'P' then convert(varchar(20),c)
else '***' end c,
case @bln when 'D' then convert(varchar(20),convert(int,ao))
when 'M' then convert(varchar(20),convert(money,ao))
when 'P' then convert(varchar(20),ao)
else '***' end ao,
case @bln when 'D' then convert(varchar(20),convert(int,po))
when 'M' then convert(varchar(20),convert(money,po))
when 'P' then convert(varchar(20),po)
else '***' end po,
cnt
from #t
order by num, sub,acc,t


END
...
Рейтинг: 0 / 0
25.06.2001, 15:01
    #32008295
kindzer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оборотная ведомость
Спасибо за ответ
/пока правда не врубился/

Есть два вопроса:
1) что означают параметры - @bln varchar(10), @fond varchar(20)
2) Описание (SQL script) таблиц - AccState, Acc, PlnSub
...
Рейтинг: 0 / 0
26.06.2001, 06:44
    #32008319
SergSuper
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оборотная ведомость
Вообще-то я кинул без надежды на то, что в этом можно разобраться. Чтобы показать что не стоит показывать свои огромные процедуры в надежде что кто-нибудь посмотрит на них и поможет - смысла нет.

Но на вопросы конечно отвечу.

1. Это процедура для паевых фондов. В базе идет работа с несколькими фондами одновременно, а баланс нужен по каждому.Т.о. @fond - это код паевого фонда, а @bln - тип баланса(денежный, депо, паевой)
2. AccState - остатки и обороты по счетам; запись появляется если есть движение за этот день по счету
Аcc - просто лицевые счета
PlnSub - субсчета(более верхний уровень для Acc)

А вообще это сделано для HTML, там еще считается count(*) для rowspan.
Выводить сразу остатки по лицевым счетам с группировками по разделам и т.д.
...
Рейтинг: 0 / 0
26.06.2001, 15:09
    #32008388
kindzer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оборотная ведомость
Меня, вообще то не интересовал внутренний запрос, он и так работает шустро!
Медленно (относительно) работает внешний!
Спасибо за урок! Больше не буду кидать всю SP... Надо выделять суть.
Интересен внешний запрос: Как к дереву прикрутить остатки?

select Счет, Описание, sum(СуммаД), sum(СуммаК) ...
from ПланСчетов "plan"
left join ( ххххх ) oborotka on oborotka.Счет like rtrim(plan.Счет)+'%'
---------------------------------------
Маленький пример:
Счета Наименование Сумма ...
10 Материалы 10000 ...
10/1 Материалы 5000 ...
10/3 Топливо 3000 ...
10/5 Запчасти 2000 ...
10/5/1 Запчасти к БО 1500 ...
10/5/2 Запчасти к а/т 500 ...
...
Рейтинг: 0 / 0
27.06.2001, 06:12
    #32008410
SergSuper
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оборотная ведомость
Если Вы всё же посмотрите что я написал, то заметите что у меня нет outer join-ов(я так понял, что Вы это подразумеваете под термином "внешний запрос").

Принцип такой. Есть некая таблица
create table #p(
acc varchar(30), -- счет
si dec(19,6), -- сальдо входящее (In)
d dec(19,6), -- дебет
c dec(19,6), -- кредит
so dec(19,6)) -- сальдо исходящее (Out)

Сначала туда вносятся входящие остатки по счету, остальные значения нули, потом обороты и потом исходщие остатки.
Т.е. примерно так
insert #p select acc, s,0,0,0 from ....
insert #p select acc, 0,d,c,0 from ....
insert #p select acc, 0,0,0,s from ....

А потом значения из этой таблицы переносятся в другую, но уже с группировкой(у меня там несколько сложнее - еще разбивается на актив и пассив):

insert #t
select acc, sum(si),sum(d),sum(c),sum(so)
from #p
group by acc

Вообщем: пишите попроще и будет быстрее работать, и самому понятней, и "люди к Вам потянуться"
...
Рейтинг: 0 / 0
27.06.2001, 17:20
    #32008471
kindzer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оборотная ведомость
Опять мы не про то !...

Сама Оборотка находится просто и мгновенно.
И не важно как одним запросом или 3-4 с использованием врем.таблиц.
(зря я ее кинул в 1 вопросе)

Вопрос не в этом!
Надо к плану счетов (дереву) присоединить оборотку,
и рассчитать остатки на счетах верхнего уровня,
типа:

на счете 10: 10000 = 5000 + 3000 + 1500 + 500 (10/1 + 10/3 + 10/5/1 + 10/5/2)
на счете 10/5: 2000 = 1500 + 500 (10/5/1 + 10/5/2)

В моем (1) "огромном" запросе медленно
работает объединение Плана счетов с обороткой
------ on об.Счет like rtrim(plan.Счет)+'%' -------- !!!
( join быстро работает когда on а.Acc=b.Acc, а не Like )

Итак:
По Вашему совету я разбил свою SP как в последнем ответе
и после последнего Insert #t select acc, sum(si),sum(d),sum(c),sum(so) from #p group by acc

1) вариант (используя insert, update)

insert into #t1 -- #t1 такая же как #t
select Acc, NAMES, 0, 0, 0, 0
from ПланСчетов

-- далее собираю si, d, c, so из #t на cчета более высокого уровня
update #t1 set si = isnull((select sum(si) from #t where #t.Acc like rtrim(#t1.Acc)+'%'),0),
d = isnull((select sum(D) from #t where #t.Acc like rtrim(#t1.Acc)+'%'),0),
c = isnull((select sum(C) from #t where #t.Acc like rtrim(#t1.Acc)+'%'),0),
so = isnull((select sum(so) from #t where #t.Acc like rtrim(#t1.Acc)+'%'),0)

select * from #t1 order by Acc
~ 24 секунды (всего) /часть спишем на индексы, в Плане счетов 1956 счетов, максимум 8 уровней/

2) вариант (используя объединение)

select Acc, Names, sum(si), sum(d), sum(c), sum(so)
from ПланСчетов left join #t on #t.Acc like rtrim(ПланСчетов.Acc)+'%'
group by Acc, Names

~ 9 секунд (всего)

Ни чего то я не выйграл!!!!
Было то ~ 5-6 сек.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Оборотная ведомость / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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