Имя: Пароль:
1C
1C 7.7
v7: Нужна помощь с прямым запросом
0 zenon46
 
19.02.20
16:24
Доброго всем дня!
Нужна помощь с запросом, главная проблема состоит в том, что на вход в запрос подается список из 3500 элементов номенклатуры, а на выходе получаем 412, где-то часть теряется, что не есть хорошо(
Суть самого запроса такая, по списку номенклатуры
1. нужно найти партию сформированную определенным типом документа
2. по этому же списку нужно получить остаток на дату
3. по этому же списку нужно посчитать усредненную себестоимость
Вот текст запроса, подзапросы идут в том же порядке как и перечислены тут

    |SELECT
    |    temp.val,
    |    Спр.Code                                         AS Код,    
    |    subsel.Номенклатура                             AS [Номенклатура $Справочник.Номенклатура],
    |    $Спр.БазоваяЕдиница                             AS [БазоваяЕдиница $Справочник.Единицы],
    |   Isnull(Рег.Date_Time_IDDOC,'-')                    [ДатаПрих],
    |    $Рег.СуммаРуб                                     AS [СуммаРуб $Число],
    |    $Рег.Количество                                 AS [Количество $Число],    
    |    ($Рег.СуммаРуб/$Рег.Количество)                 AS [ЦенаПослПрих $Число],
    |    $Рег.Партия                                     AS [Партия $Справочник.Партии],
    |    CAST(LEFT(Рег.Date_Time_IDDoc, 8)                 AS DateTime) as ДатаПослПрих,
    |   $Спр.МинОстаток                                 AS [МинОстаток $Число],
    |   $Спр.КолЗаказа                                     AS [КолЗаказа $Число],
    |    balance.Количество                                 AS [Остаток $Число],
    |   CASE WHEN ($Рег.СуммаРуб IS NULL) THEN 0 ELSE (sebestoimost.СуммаРуб/sebestoimost.Количество) END AS [Себестоимость $Число],
    |   CASE WHEN ($Рег.СуммаРуб IS NULL) THEN 0 ELSE 1 END AS [Признак $Число]    
    |FROM
    |    #TempTable
    |    temp left join
    |(
    |SELECT
    |    $Рег.Номенклатура AS [Номенклатура],
    |    MAX(Рег.Date_Time_IDDOC) AS ДатаПослПрихода
    |FROM
    |    $Регистр.ПартииНаличие as Рег
    |INNER JOIN
    |    _1Sjourn as ЖурналДок ON ЖурналДок.IDDoc = Рег.IDDoc    
    |INNER JOIN
    |    $Справочник.Партии AS СпрП ON СпрП.ID = $Рег.Партия
    |INNER JOIN
    |    $Справочник.Контрагенты AS СпрК ON СпрК.ID = $СпрП.Поставщик
    |WHERE
    |   ЖурналДок.iddocdef = $ВидДокумента.ПоступлениеТМЦ_Склад AND    
    |    $Рег.Номенклатура IN (SELECT val FROM #TempTable) AND    
    |    $Рег.Фирма = :ВбрФирма AND    
    |    $СпрП.Поставщик NOT IN (SELECT val FROM #TableKontr)    
    |GROUP BY
    |    $Рег.Номенклатура
    |) subsel ON temp.val = subsel.Номенклатура        
    |LEFT JOIN
    |(
    |SELECT
    |    Рег.Номенклатура AS [Номенклатура],    
    |    Рег.КоличествоОстаток AS Количество
    |FROM
    |    $РегистрОстатки.ОстаткиТМЦ(:ВыбДата~,,Фирма = :ВбрФирма AND Номенклатура IN (SELECT val FROM #TempTable),(Номенклатура),(Количество)) AS Рег
    |) balance ON temp.val = balance.Номенклатура
    |LEFT JOIN
    |(
    |SELECT
    |    Рег.Номенклатура AS [Номенклатура],    
    |    Рег.КоличествоОстаток AS Количество,
    |    Рег.СуммаРубОстаток AS СуммаРуб
    |FROM
    |   $РегистрОстатки.ПартииНаличие(:ВыбДата~,,Фирма = :ВбрФирма AND Номенклатура IN (SELECT val FROM #TempTable),(Номенклатура),(Количество,СуммаРуб)) AS Рег
    |) sebestoimost ON temp.val = sebestoimost.Номенклатура    
    |INNER JOIN
    |    $Справочник.Номенклатура AS Спр ON Спр.ID = temp.val     
    |LEFT JOIN
    |    $Регистр.ПартииНаличие AS Рег ON $Рег.Номенклатура = subsel.Номенклатура AND Рег.Date_time_iddoc=subsel.ДатаПослПрихода    
    |ORDER BY
    |    Спр.Code
    |";
1 mikecool
 
19.02.20
16:25
кастую в соединения
2 mikecool
 
19.02.20
16:25
ON Спр.ID = temp.val  - вот здесь скорее всего
3 Ёпрст
 
19.02.20
16:34
(0)вот это поменяй на  left и увидишь, где Спр.ID<> temp.val

  |INNER JOIN
    |    $Справочник.Номенклатура AS Спр ON Спр.ID = temp.val
4 zenon46
 
19.02.20
16:37
(3) поменял..результат тот же
5 Ёпрст
 
19.02.20
16:39
(4) чудес не бывает или одна из черепашек врёт

  |SELECT
    |    temp.val
    |FROM
    |    #TempTable

так, сколько видишь элементов в результате ?
6 zenon46
 
19.02.20
16:42
(5) Так :
SELECT
val
FROM
#TempTable

Все 3500
7 Ёпрст
 
19.02.20
16:44
(6)
а так ?
|SELECT
    |    temp.val
    |FROM
    |    #TempTable

|INNER JOIN
    |    $Справочник.Номенклатура AS Спр ON Спр.ID = temp.val
8 zenon46
 
19.02.20
16:47
(7) Так :
SELECT
    val
FROM
    #TempTable
INNER JOIN
    $Справочник.Номенклатура AS Спр ON Спр.ID = val

Все 3500
9 Ёпрст
 
19.02.20
16:58
(9) ну и добавляй всё остальное
10 zenon46
 
19.02.20
16:59
Урезал запрос до такого : в резултатх стало еще больше чем в списке....странно

SELECT
temp.val,
Спр.Code           AS Код,
subsel.Номенклатура        AS [Номенклатура $Справочник.Номенклатура],
$Спр.БазоваяЕдиница        AS [БазоваяЕдиница $Справочник.Единицы],
   Isnull(Рег.Date_Time_IDDOC,'-')        [ДатаПрих],
$Рег.СуммаРуб          AS [СуммаРуб $Число],
$Рег.Количество            AS [Количество $Число],
($Рег.СуммаРуб/$Рег.Количество)        AS [ЦенаПослПрих $Число],
$Рег.Партия             AS [Партия $Справочник.Партии],
CAST(LEFT(Рег.Date_Time_IDDoc, 8)     AS DateTime) as ДатаПослПрих,
   $Спр.МинОстаток            AS [МинОстаток $Число],
   $Спр.КолЗаказа          AS [КолЗаказа $Число],

   CASE WHEN ($Рег.СуммаРуб IS NULL) THEN 0 ELSE 1 END AS [Признак $Число]
FROM
#TempTable
temp left join
(
SELECT
$Рег.Номенклатура AS [Номенклатура],
MAX(Рег.Date_Time_IDDOC) AS ДатаПослПрихода
FROM
$Регистр.ПартииНаличие as Рег
INNER JOIN
_1Sjourn as ЖурналДок ON ЖурналДок.IDDoc = Рег.IDDoc
INNER JOIN
$Справочник.Партии AS СпрП ON СпрП.ID = $Рег.Партия
INNER JOIN
$Справочник.Контрагенты AS СпрК ON СпрК.ID = $СпрП.Поставщик
WHERE
   ЖурналДок.iddocdef = $ВидДокумента.ПоступлениеТМЦ_Склад AND
$Рег.Номенклатура IN (SELECT val FROM #TempTable) AND
$Рег.Фирма = :ВбрФирма AND
$СпрП.Поставщик NOT IN (SELECT val FROM #TableKontr)
GROUP BY
$Рег.Номенклатура
) subsel ON temp.val = subsel.Номенклатура  
INNER JOIN
$Справочник.Номенклатура AS Спр ON Спр.ID = temp.val  
LEFT JOIN
$Регистр.ПартииНаличие AS Рег ON $Рег.Номенклатура = subsel.Номенклатура AND  Рег.Date_time_iddoc=subsel.ДатаПослПрихода
ORDER BY
Спр.Code
11 Ёпрст
 
19.02.20
17:00
(10) че го странного то ? left join же
12 Ёпрст
 
19.02.20
17:01
у тя в temp Номенклатура Валенки

а в подзапросе или в регистре

Номенклатура Валенки Количество 10
Номенклатура Валенки Количество 20
Номенклатура Валенки Количество 30

вот и будет 3 строки
13 zenon46
 
19.02.20
17:05
(12) ды в подзапросе должна быть одна запись по каждой номенклатуре за счет : MAX(Рег.Date_Time_IDDOC) AS ДатаПослПрихода И GROUP BY
$Рег.Номенклатура
14 zenon46
 
19.02.20
17:08
Вот : https://prnt.sc/r4mumc  видим одну запись на один товар
15 Sserj
 
19.02.20
17:08
(10) 1. Собери "INNER JOIN"-ы вверху а left-ы внизу, планировщику будет намного легче и меньше вероятности
ошибки что inner-ом сложишь не то что хотел.
FROM
#TempTable as temp
INNER JOIN
$Справочник.Номенклатура AS Спр ON Спр.ID = temp.val
left join ...

2. Переименуй все алиасы в уникальные. У тебя несколько раз используется Рег, в доке к 1С++ сказано:
Замечание! На текст запроса накладывается дополнительное ограничение: псевдонимы таблиц, имена которых транслируются из метаимен, не должны повторяться, иначе трансляция метаимени полей через псевдоним таблицы может быть неверной.

Пару раз напарывался, хоть все верно написано, хоть тресни, а выдается ерунда.
16 Sserj
 
19.02.20
17:14
(10) Увеличение строк явно дает
..
LEFT JOIN
$Регистр.ПартииНаличие AS Рег ON $Рег.Номенклатура = subsel.Номенклатура AND  Рег.Date_time_iddoc=subsel.ДатаПослПрихода
ORDER BY
Спр.Code

Видимо в каком то поступлении товар создает несколько партий, возможно по разной цене.
17 zenon46
 
19.02.20
17:16
(16) да, такое вполне возмжно....буду искать в этом направлении
18 zenon46
 
20.02.20
09:03
Что удалось выяснить, собирал попорядку все подзапросы, и как только в SELECT лист я добавляю, в выборке остается хрен пойми что от всего списка :

CASE WHEN ($Рег.СуммаРуб IS NULL) THEN 0 ELSE (sebestoimost.СуммаРуб/sebestoimost.Количество) END AS [Себестоимость $Число]
19 zenon46
 
20.02.20
10:16
Все дело в операции деления...как-то не понятно оно рабоатет, проверил так :
20 zenon46
 
20.02.20
10:16
Вот запрос :
SELECT
    Спр.Code AS Код,
        РегП3.КоличествоОстаток AS Количество,
        РегП3.СуммаРубОстаток AS СуммаРуб,
       РегП3.СуммаРубОстаток/РегП3.КоличествоОстаток AS Себестоимость
    FROM
       $РегистрОстатки.ПартииНаличие(:ВыбДата~,,Фирма = :ВбрФирма AND Номенклатура IN (SELECT val FROM #TempTable),(Номенклатура),(Количество,СуммаРуб)) AS РегП3
    LEFT JOIN
        $Справочник.Номенклатура AS Спр ON Спр.ID = РегП3.Номенклатура
    ORDER BY
        Спр.Code

С делением 25 строк в выборке, убираем деление 1184
21 trad
 
20.02.20
10:25
деление на 0
оно выдается сервером не ошибкой а предупреждением
в 1с++, обдцрекордсет это не понимает и получает только часть результата, при этом никак не ругаясь

получить текст запроса Отладка(1)
полученный текст выполни QA или SMS - все увидишь сам
22 trad
 
20.02.20
10:26
РегП3.СуммаРубОстаток / nullif(РегП3.КоличествоОстаток, 0)
23 zenon46
 
20.02.20
10:27
(22) я пробовал так CASE WHEN (Рег.КоличествоОстаток IS NULL) THEN 0 ELSE (Рег.СуммаРубОстаток/Рег.КоличествоОстаток) END AS Себестоиомсть, один хрен
вот что в трансляции запроса :
{call sp_executesql(N'SELECT
Рег.Номенклатура AS [Номенклатура],  
Рег.КоличествоОстаток AS Количество,
Рег.СуммаРубОстаток AS СуммаРуб,
CASE WHEN (Рег.КоличествоОстаток IS NULL) THEN 0 ELSE (Рег.СуммаРубОстаток/Рег.КоличествоОстаток) END AS Себестоиомсть
FROM
   (
select
rg328_vt.sp331 as Номенклатура,
sum(rg328_vt.sp342) as КоличествоОстаток,
sum(rg328_vt.sp343) as СуммаРубОстаток
from rg328 as rg328_vt (nolock)
where rg328_vt.period=@_CP_2
and (rg328_vt.sp4061 = @ВбрФирма0 AND rg328_vt.sp331 IN (SELECT val FROM #TempTable))
group by
rg328_vt.sp331
having
sum(rg328_vt.sp342) <> 0 or
sum(rg328_vt.sp343) <> 0
) as Рег', N'@ВбрФирма0 char(9),@_CP_2 smalldatetime'
,'     1   ',{d '2020-02-01'})}
24 trad
 
20.02.20
10:28
Рег.КоличествоОстаток у тебя не null, а 0
25 zenon46
 
20.02.20
10:28
(22) фак, сработало....можно объяснить почему ?
26 trad
 
20.02.20
10:30
на ноль делить нельзя...
на нул - можно

(с)Мюллер )))
27 zenon46
 
20.02.20
10:32
(26) да, но ОНО ошибки то не выдавало, когда пробовал принудительно select 1/0 - была ошибка
28 trad
 
20.02.20
10:34
повторю, проведи эти эксперименты в QA или SMS - все увидишь сам
29 zenon46
 
20.02.20
10:34
(28) спасибо, поправил верхний запрос из (1) и все заработало как надо....
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой