Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Горячая тема (более 10 ответов) Остатки на КАЖДЫЙ день (число прочтений - 3476 )
jj
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 27
Зарегистрирован: 09. Октября 2009
Остатки на КАЖДЫЙ день
04. Мая 2012 :: 16:43
Печать  
Доброго времени суток!

Перерыл половину инета, но ответа к сожалению так и не нашел.
Написал такой вот запрос :
Код
Выбрать все
ТекстЗапроса = "
	|SELECT
	|	ОстаткиТМЦОстаткиОбороты.Фирма [Фирма $Справочник.Фирмы],
	|	ОстаткиТМЦОстаткиОбороты.Номенклатура [Номенклатура $Справочник.Номенклатура],
	|	ОстаткиТМЦОстаткиОбороты.Склад [Склад $Справочник.Склады],
	|	ОстаткиТМЦОстаткиОбороты.Период as ДеньОстатка,
	|	SUM(ОстаткиТМЦОстаткиОбороты.КоличествоНачальныйОстаток) as Нач,
	|	SUM(ОстаткиТМЦОстаткиОбороты.КоличествоПриход) as Прих,
	|	SUM(ОстаткиТМЦОстаткиОбороты.КоличествоРасход) as Расх,
	|	SUM(ОстаткиТМЦОстаткиОбороты.КоличествоКонечныйОстаток) as Кон
	|FROM
	|	,,,(Фирма, Номенклатура, Склад),(Количество)) AS ОстаткиТМЦОстаткиОбороты
	|GROUP BY
	|	ОстаткиТМЦОстаткиОбороты.Период,
	|	ОстаткиТМЦОстаткиОбороты.Фирма,
	|	ОстаткиТМЦОстаткиОбороты.Склад,
	|	ОстаткиТМЦОстаткиОбороты.Номенклатура
	|ORDER BY
	|	ОстаткиТМЦОстаткиОбороты.Номенклатура,
	|	ОстаткиТМЦОстаткиОбороты.Фирма,
	|	ОстаткиТМЦОстаткиОбороты.Склад
	|";

	RS.УстановитьТекстовыйПараметр("НачДата", ВыбНачПериода);
	RS.УстановитьТекстовыйПараметр("КонДата", ВыбКонПериода); 



И вот все бы хорошо, но.... выводит остатки только на те даты, когда было движение. Можно ли каким-либо способом получить остатки на все даты из выбранного периода, независимо от наличия/отсутствия движений ?
  
Наверх
 
IP записан
 
antoneus
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 54
Зарегистрирован: 16. Марта 2009
Пол: Мужской
Re: Остатки на КАЖДЫЙ день
Ответ #1 - 04. Мая 2012 :: 17:46
Печать  
Да. Либо соединять с таблицей, заполненной датами, либо результат загнать в ИТЗ, подготовить список значений со всеми датами из периода и в цикле выводить итог по фильтру со значением даты из списка.
  
Наверх
 
IP записан
 
jj
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 27
Зарегистрирован: 09. Октября 2009
Re: Остатки на КАЖДЫЙ день
Ответ #2 - 04. Мая 2012 :: 17:49
Печать  
что-то типа такого ?
Код
Выбрать все
	ТекстЗапроса = "
		|IF OBJECT_ID(N'tempdb.dbo.#Дни') IS NOT NULL
		|	DROP TABLE #Дни
		|";
	RS.Выполнить(ТекстЗапроса);

	ТекстЗапроса = "
		|CREATE TABLE #Дни (День DateTime)
		|";
	RS.Выполнить(ТекстЗапроса);

	Для ТекДата = ВыбНачПериода По ВыбКонПериода Цикл
		ТекстЗапроса = "
			|INSERT INTO #Дни VALUES (:ТекДата)
			|";

		RS.УстановитьТекстовыйПараметр("ТекДата", ТекДата);
		RS.Выполнить(ТекстЗапроса);
	КонецЦикла;
 



как ее приджоинить к остаткам ? не пойму
  
Наверх
 
IP записан
 
antoneus
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 54
Зарегистрирован: 16. Марта 2009
Пол: Мужской
Re: Остатки на КАЖДЫЙ день
Ответ #3 - 04. Мая 2012 :: 18:05
Печать  
Так, стоп, всё неправильно прочитал Улыбка
  
Наверх
 
IP записан
 
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Re: Остатки на КАЖДЫЙ день
Ответ #4 - 05. Мая 2012 :: 08:33
Печать  
Остатки не хранятся в базе "на каждый день", они рассчитываются. Поэтому варианты:
1. Рисуем хитромудрый запрос к SQL, который выдаст нам данные нужной структуры
2. Берем остатки на начало рассчетного периода, берем таблицу движений и рассчитываем данные самостоятельно
Я бы сделал по второму варианту
  
Наверх
ICQ  
IP записан
 
villy
Senior Member
****
Отсутствует



Сообщений: 287
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Остатки на КАЖДЫЙ день
Ответ #5 - 10. Мая 2012 :: 12:27
Печать  
  
Наверх
IP записан
 
vandalsvq
1c++ power user
Отсутствует


Я всего лишь als-особиратель
;-)

Сообщений: 2487
Местоположение: Уфа
Зарегистрирован: 18. Июля 2007
Пол: Мужской
Re: Остатки на КАЖДЫЙ день
Ответ #6 - 10. Мая 2012 :: 16:58
Печать  
А использовать класс "ПрямойЗапрос"??? У него есть метод параметр ПЕРИОД <ДОПОЛНЕНИЕ>. В результате если с дополнением то получаете таблицу на каждый период. Вот.
Ну или если религия не позволяет, вариант просто посмотреть реализацию в классе. Там конечно не сразу понятно, но зато вроде правильно
  

Отхожу от дел. Долго и мучительно.
Наверх
IP записан
 
val
Full Member
***
Отсутствует


Дорогу осиливает идущий

Сообщений: 137
Зарегистрирован: 07. Июля 2006
Re: Остатки на КАЖДЫЙ день
Ответ #7 - 11. Мая 2012 :: 07:11
Печать  
(0) Давай свой почтовый ящик.
  
Наверх
 
IP записан
 
jj
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 27
Зарегистрирован: 09. Октября 2009
Re: Остатки на КАЖДЫЙ день
Ответ #8 - 17. Мая 2012 :: 04:32
Печать  
нашел таки на просторах инета.
1. получаем остатки и обороты на даты, когда они были.
2. формируем таблицу дат из необходимого периода.
3. дополняем таблицу недостающими значениями.
  
Наверх
 
IP записан
 
val
Full Member
***
Отсутствует


Дорогу осиливает идущий

Сообщений: 137
Зарегистрирован: 07. Июля 2006
Re: Остатки на КАЖДЫЙ день
Ответ #9 - 17. Мая 2012 :: 07:14
Печать  
(8) +100000. Вопрос только в способе реализации.
Можно итоговую таблицу со всеми датами и остатками формировать прямыми запросами.
А можно прямыми только остатки и движения, а потом рассчитывать у себя недостающие даты.
Я делал первый способ.
  
Наверх
 
IP записан
 
jj
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 27
Зарегистрирован: 09. Октября 2009
Re: Остатки на КАЖДЫЙ день
Ответ #10 - 17. Мая 2012 :: 07:36
Печать  
а я второй Улыбка
  
Наверх
 
IP записан
 
jj
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 27
Зарегистрирован: 09. Октября 2009
Re: Остатки на КАЖДЫЙ день
Ответ #11 - 18. Мая 2012 :: 03:05
Печать  
поскольку ине нужно было тянуть данные не в 1С от 1С++ пришлось отказаться. получился такой запрос:
Код
Выбрать все
IF OBJECT_ID(N'tempdb.dbo.#ОстаткиОбороты') IS NOT NULL
	DROP TABLE #ОстаткиОбороты

SET NOCOUNT ON

CREATE TABLE #ОстаткиОбороты(
	Период datetime,
	Номенклатура char(9),
	Фирма char(9),
	Склад char(9),
	Количество numeric(38,3),
	primary key clustered (Фирма,Номенклатура,Склад,Период))

INSERT INTO #ОстаткиОбороты
SELECT
	Период,
	Номенклатура,
	Фирма,
	Склад,
	SUM(Количество) Количество
FROM
	(
	SELECT
		'2012.03.01' Период,
		Номенклатура,
		Фирма,
		Склад,
		КоличествоОстаток Количество
	FROM
		(
		SELECT
			rg6645_vt.sp6639 AS Фирма,
			rg6645_vt.sp6640 AS Номенклатура,
			rg6645_vt.sp6641 AS Склад,
			SUM(rg6645_vt.sp6643) AS КоличествоОстаток
		FROM
			rg6645 AS rg6645_vt (nolock)
		WHERE
			rg6645_vt.period='20120201'
		GROUP BY
			rg6645_vt.sp6639,
			rg6645_vt.sp6640,
			rg6645_vt.sp6641
		HAVING
			SUM(rg6645_vt.sp6643) <> 0
		) AS Итогов

	UNION ALL

	SELECT
		Период,
		Номенклатура,
		Фирма,
		Склад,
		КоличествоПриход-КоличествоРасход Количество
	FROM
		(
		SELECT
			ra6645_vt.sp6639 AS Фирма,
			ra6645_vt.sp6640 AS Номенклатура,
			ra6645_vt.sp6641 AS Склад,
			cast(left(j6645_vt.date_time_iddoc, 8) AS datetime) AS Период,
			SUM(CASE WHEN ra6645_vt.debkred = 0 THEN ra6645_vt.sp6643 ELSE 0 END) AS КоличествоПриход,
			SUM(CASE WHEN ra6645_vt.debkred = 1 THEN ra6645_vt.sp6643 ELSE 0 END) AS КоличествоРасход
		FROM
			ra6645 AS ra6645_vt (nolock)
		INNER JOIN
			_1sjourn AS j6645_vt (nolock) ON j6645_vt.iddoc = ra6645_vt.iddoc
		WHERE j6645_vt.date_time_iddoc > '20120301' AND
			j6645_vt.date_time_iddoc < '20120331Z' AND
			j6645_vt.rf6645 = 0x1
		GROUP BY
			ra6645_vt.sp6639,
			ra6645_vt.sp6640,
			ra6645_vt.sp6641,
			CAST(left(j6645_vt.date_time_iddoc, 8) AS datetime)
	 	HAVING
			SUM(CASE WHEN ra6645_vt.debkred = 0 THEN ra6645_vt.sp6643 ELSE 0 END) <> 0 OR
			SUM(CASE WHEN ra6645_vt.debkred = 1 THEN ra6645_vt.sp6643 ELSE 0 END) <> 0
		) AS Итогов
	) AS Итогов
GROUP BY
	Период,
	Номенклатура,
	Фирма,
	Склад
ORDER BY
	Номенклатура,
	Период,
	Фирма,
	Склад

IF OBJECT_ID(N'tempdb.dbo.#Дни') IS NOT NULL
	DROP TABLE #Дни
CREATE TABLE #Дни (Период datetime primary key)

DECLARE @i as datetime
SET @i = '2012.02.29'

WHILE @i < '2012.03.31'
BEGIN
	set @i = DATEADD(day,1,@i)
	INSERT INTO #Дни VALUES (@i)
END

IF OBJECT_ID(N'tempdb.dbo.#ЗапасСредний') IS NOT NULL
	DROP TABLE #ЗапасСредний

CREATE TABLE #ЗапасСредний
	(
	Период datetime,
	Номенклатура char(9),
	Фирма char(9),
	Склад char(9),
	Количество numeric(38,3),
	primary key clustered (Фирма,Номенклатура,Склад,Период)
	)

INSERT INTO #ЗапасСредний
	SELECT
		crosstable.Период,
		crosstable.Номенклатура,
		crosstable.Фирма,
		crosstable.Склад,
		ISNULL(vt_totalreg.Количество,0) Количество
	FROM (
		SELECT
			Период Период,
			vt_def.Номенклатура,
			vt_def.Фирма,
			vt_def.Склад
		FROM
			#Дни AS datetable
			CROSS JOIN (SELECT DISTINCT Фирма,Номенклатура,Склад FROM #ОстаткиОбороты) AS vt_def
		) AS crosstable
	LEFT JOIN
		#ОстаткиОбороты AS vt_totalreg ON crosstable.Период = vt_totalreg.Период
		AND crosstable.Фирма = vt_totalreg.Фирма
		AND crosstable.Номенклатура = vt_totalreg.Номенклатура
		AND crosstable.Склад = vt_totalreg.Склад

DROP TABLE #ОстаткиОбороты
DROP TABLE #Дни

DECLARE @Номенклатура char(9)
DECLARE @Фирма char(9)
DECLARE @Склад char(9)
DECLARE @Количество numeric(38,3)
UPDATE #ЗапасСредний
SET
	@Количество = Количество = CASE WHEN @Фирма = Фирма AND @Номенклатура = Номенклатура AND @Склад = Склад THEN @Количество+Количество ELSE Количество END,
	@Фирма = Фирма,
	@Номенклатура = Номенклатура,
	@Склад = Склад

SELECT * FROM #ЗапасСредний ORDER BY Номенклатура 

  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Остатки на КАЖДЫЙ день
Ответ #12 - 21. Мая 2012 :: 05:21
Печать  
Код
Выбрать все
		SUM(CASE WHEN ra6645_vt.debkred = 0 THEN ra6645_vt.sp6643 ELSE 0 END) AS КоличествоПриход,
			SUM(CASE WHEN ra6645_vt.debkred = 1 THEN ra6645_vt.sp6643 ELSE 0 END) AS КоличествоРасход 



Тут case не нужен, пользуемся простым умножением

Group by во вложенных подзапросах тоже лишнее, как и having, тем более с OR
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать