Имя: Пароль:
1C
1C 7.7
v7: В результате выполнения запроса "нехватка оперативной памяти"
0 zenon46
 
28.12.19
13:09
Доброго дня! Есть запрос для получения остатков оборотов и поступлений (с отбором по виду документа), в разрезе каждого дня из интервала, но в результате по большому периоду и большому списку номенклатуры, имеем падение предприятия с ошибкой в нехватке оперативной памяти. Как можно оптимизировать / переделать запрос, что бы мы имели по товару "свернутые" цифры по интервалу, начальный остаток посчитаем отдельно.
Вот собственно запрос :
    МетаДата = СоздатьОбъект("MetaDataWork");
    ТекстЗапроса = "
    |SET NOCOUNT ON
    |;  
    |IF EXISTS(SELECT * FROM tempdb..sysobjects WHERE id = object_id('tempdb..#Период'))
    |    DROP TABLE #Период
    |;
    |CREATE TABLE #Период (val char(9) PRIMARY KEY)
    |;
    |DECLARE @НачДата as DATETIME
    |SET @НачДата = '"+МетаДата.ПолучитьСтрИзДаты(НачДатаПрод)+"'
    |DECLARE @КонДата as DATETIME
    |SET @КонДата = '"+МетаДата.ПолучитьСтрИзДаты(КонДатаПрод)+"'
    |WHILE @НачДата <= @КонДата
    |BEGIN
    |INSERT INTO #Период VALUES (CONVERT(char(8), @НачДата, 112))
    |SET @НачДата = dateadd(DAY, 1, @НачДата)
    |END
    |;
    |IF EXISTS(SELECT * FROM tempdb..sysobjects WHERE id = object_id('tempdb..#Итоги'))
    |    DROP TABLE #Итоги
    |;
    |CREATE TABLE #Итоги (Дата char(8), Товар char(9), Остаток float, Оборот float, Поступление float)
    |;
    |CREATE INDEX DateItem ON #Итоги (Товар,Дата)
    |;
    |INSERT INTO #Итоги (Дата,Товар,Остаток,Оборот,Поступление)
    |SELECT
    |    ДатыТовары.Дата             as [Дата $Дата],
    |    ДатыТовары.Товар            as [Товар $Справочник.Номенклатура],
    |    SUM(ДатыТовары.Остаток)     as [Остаток $Число],
    |    SUM(ДатыТовары.Оборот)      as [Оборот $Число],
    |    SUM(ДатыТовары.Поступление) as [Поступление $Число]
    |FROM
    |  (SELECT
    |     #Период.val    as [Дата],
    |     #TempTable.val as [Товар],
    |     0              as [Остаток],
    |     0              as [Оборот],
    |     0              as [Поступление]
    |  FROM
    |    #Период CROSS JOIN #TempTable
    |UNION ALL
    |  SELECT
    |     :НачДата,
    |     Остатки.Номенклатура,
    |     Остатки.КоличествоОстаток,
    |     0,
    |     0
    |FROM
    |    $РегистрОстатки.ОстаткиТМЦ(:НачДата,,Фирма = :ВыбФирма AND Номенклатура IN (SELECT val FROM #TempTable),(Номенклатура),(Количество)) as Остатки
    |UNION ALL
    |   SELECT
    |      SUBSTRING(Обороты.Date_Time_Iddoc,1,8)                                                                     AS [Дата],
    |      $Обороты.Номенклатура                                                                                       AS [Товар],
    |      0                                                                                                         AS [Остаток],
    |      SUM(CASE WHEN Обороты.DEBKRED = 0 THEN $Обороты.Количество ELSE $Обороты.Количество * (-1) END)             AS [Оборот],
    |      SUM(CASE WHEN Обороты.IDDOCDEF = $ВидДокумента.ПоступлениеТМЦ_Склад THEN $Обороты.Количество ELSE 0 END) AS [Поступление]
    |    FROM
    |      $Регистр.ОстаткиТМЦ as Обороты
    |    WHERE
    |      Обороты.Date_Time_Iddoc between :НачДата AND :КонДата~ AND
    |      $Обороты.Номенклатура IN (SELECT val FROM #TempTable) AND
    |       $Обороты.Фирма = :ВыбФирма
    |    GROUP BY
    |       SUBSTRING(Обороты.Date_Time_Iddoc, 1, 8), $Обороты.Номенклатура, Обороты.IDDoc    
    |  ) as ДатыТовары
    |GROUP BY
    |  ДатыТовары.Дата, ДатыТовары.Товар
    |;
    |DROP TABLE #Период
    |;
    |DECLARE @CurrentMove   as float
    |DECLARE @CurrentQty    as float
    |DECLARE @NextQty       as float
    |DECLARE @CurrentItem   as char(9)
    |DECLARE @LastItem      as char(9)
    |SET @LastItem = ''
    |
    |DECLARE cur CURSOR LOCAL FORWARD_ONLY FOR
    |SELECT Оборот,Товар,Остаток
    |FROM #Итоги
    |ORDER BY Товар,Дата
    |FOR UPDATE
    |
    |OPEN cur
    |FETCH NEXT FROM cur INTO @CurrentMove, @CurrentItem, @CurrentQty
    |WHILE @@FETCH_STATUS = 0
    |BEGIN
    |  IF NOT @LastItem = @CurrentItem
    |    BEGIN
    |       SET @NextQty = @CurrentQty + @CurrentMove
    |       SET @LastItem = @CurrentItem
    |    END
    |  ELSE
    |    BEGIN
    |      UPDATE #Итоги
    |      SET Остаток = @NextQty
    |      WHERE CURRENT OF cur
    |      SET @NextQty = @NextQty + @CurrentMove
    |    END
    |FETCH NEXT FROM cur INTO @CurrentMove, @CurrentItem, @CurrentQty
    |END
    |;
    |CLOSE cur
    |;
    |deallocate cur
    |;
    |SELECT
    |    Товары.CODE       as [Код $Строка],
    |    Итоги.Товар       as [Номенклатура $Справочник.Номенклатура],
    |    Итоги.Остаток     as [Остаток $Число],
    |    Итоги.Поступление as [Поступление $Число],    
    |    Итоги.Дата        as [Дата $Дата],
    |    Итоги.Остаток + Итоги.Оборот as [ОстатокКонДень $Число],
    |    (Итоги.Остаток + (Итоги.Остаток + Итоги.Оборот))/2 as [СредДневОстаток $Число]
    |FROM
    |   #Итоги as Итоги
    |   JOIN $Справочник.Номенклатура as Товары ON Итоги.Товар = Товары.ID
    |ORDER BY
    |   Итоги.Дата, Товары.DESCR, Товары.ID
    |;
    |DROP TABLE #Итоги
    |;
    |SET NOCOUNT OFF
    |";
1 zenon46
 
28.12.19
14:52
Вроде как обошлось просто через SUM сделать, проверяю.
2 zenon46
 
28.12.19
14:55
Хотя это не правильно(
3 Злопчинский
 
28.12.19
15:10
(0) "остатков оборотов и поступлений"
меня напрягает эта фраза..
какие остатки ОБОРОТОВ?
оборот - он и есть оборот. за период.
какой у него остаток?
4 zenon46
 
28.12.19
15:12
там запятой не хватает)
"остатков, оборотов, поступлений"
5 zenon46
 
28.12.19
15:13
получается из всего запроса, сумму можно дернуть только по Итоги.Поступление as [Поступление $Число], и (Итоги.Остаток + (Итоги.Остаток + Итоги.Оборот))/2 as [СредДневОстаток $Число], а дальше нужен остаток на начало периода и остаток на конец периода.
6 Злопчинский
 
28.12.19
15:13
поступлений - считаешь оборот поступлений?
7 zenon46
 
28.12.19
15:16
(6) $ВидДокумента.ПоступлениеТМЦ_Склад THEN $Обороты.Количество ELSE 0 END) AS [Поступление]  только то что пришло по этому виду документов