SQL запрос, Регистр ОстаткиТоваров не отбирает остатки по :ТекущаяДата~.
Добрый день, имеется самописная конфа под 7.7, регистр ОстаткиТоваров, база SQL. У Регистра: Измерения - Фирма, Товар, Склад и Ресурсы - ОстатокТовара.
Выдает ошибку: ... Неправильный синтаксис около , - почему?
Запрос = СоздатьОбъект("ODBCRecordset");
ТекстЗапроса = "
|SEL ECT
| ОТ.Товар AS [Товар $Справочник.Номенклатура],
| ОТ.Склад AS [Склад $Справочник.МестаХранения],
| ОТ.ОстатокТовара AS Количество
|FROM
| $Регистр.ОстаткиТоваров (:ТекущаяДата~,,Склад = :Склад,Товар, Количество) AS ОТ
//| $Регистр.ОстаткиТоваров AS ОТ
|WHERE
|ОТ.Товар IN (SELECT VAL FR OM #СписокТоваров)
|";
СпрСклад = СоздатьОбъект("Справочник.МестаХранения");
СпрСклад.НайтиПоКоду(1);;
Запрос.УстановитьТекстовыйПараметр("Склад", СпрСклад.ТекущийЭлемент());
Запрос.УстановитьТекстовыйПараметр("ТекущаяДата", ТекущаяДата());
Запрос.УложитьСписокОбъектов(СписокТоваров, "#СписокТоваров", "Номенклатура");
ПоказатьВыдает ошибку: ... Неправильный синтаксис около , - почему?
Ответы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
(1) succub1_5, нет возможности проверить, но я б попробовал так:
ТекстЗапроса = "
|SEL ECT
| ОТ.Товар AS [Товар $Справочник.Номенклатура],
| ОТ.Склад AS [Склад $Справочник.МестаХранения],
| ОТ.ОстатокТовара AS Количество
|FROM
| $Регистр.ОстаткиТоваров (:ТекущаяДата~,,Склад = :Склад AND Товар IN (SELECT VAL FR OM #СписокТоваров),(Товар), (Количество)) AS ОТ
|";
(13) succub1_5, а глянул доку, освежил память, вот так попробуете?
В результате если честно не уверен, проходил это все изрядно давно.
ТекстЗапроса = "
|SELECT
| ОТ.Товар AS [Товар $Справочник.Номенклатура],
| ОТ.Склад AS [Склад $Справочник.МестаХранения],
| ОТ.ОстатокТовара AS Количество
|FROM
| $РегистрОстатки.ОстаткиТоваров(:ТекущаяДата,,Склад = :Склад AND Товар IN (SELECT VAL FR OM #СписокТоваров),(Товар), (Количество)) AS ОТ
|";
В результате если честно не уверен, проходил это все изрядно давно.
(21) succub1_5, получить, но без 1cpp муторней.
нужно писать sql запрос по типу
где
дата2 = нужная дата,
дата1 = дата хранения итогов а период, предшествующий дата2, обычно начало месяца,
ra*, rg* и sc* заменить на названия нужных табиц, см. 1cv7.dd[s], представления остальных полей берем оттуда же.
нужно писать sql запрос по типу
sel ect
reg.ид_товара,
sc_Номенклатура.descr,
sum(reg.Количество) fr om
(sel ect fr om
rg_нужный_регистр.ид_товара,
rg_нужный_регистр.количество,
where
period = дата1
uni on
sel ect fr om
ra_нужный_регистр.ид_товара,
ra_нужный_регистр.количество * case when ra_нужный_регистр.debcred=1 then -1 else 1 end,
wh ere
ra_нужный_регистр.date_time_iddoc > дата1 and ra_нужный_регистр.date_time_iddoc < дата2) reg
inner join sc_Номенклатура on sc_Номенклатура.id = reg.ид_товара
group by reg.ид_товара,
sc_Номенклатура.descr
Показатьгде
дата2 = нужная дата,
дата1 = дата хранения итогов а период, предшествующий дата2, обычно начало месяца,
ra*, rg* и sc* заменить на названия нужных табиц, см. 1cv7.dd[s], представления остальных полей берем оттуда же.
(22) ditp, вот (в PHP) что получилось:
Только вот у ra99 (Регистр.ОстаткиТоваров) - нет date_time_iddoc.
P.S. Rg99 - РегистрИтоги.ОстаткиТоваров, Sc31 - склады, Sc33 - товары.
$date1 = date("Y-m-01");
$date2 = date("Y-m-d");
$query = "SEL ECT reg.sp101,
sc33.descr,
sum(reg.sp102)
FR OM
(SEL ECT
rg99.sp101,
rg99.sp102
FR OM rg99
WHERE rg99.period = ".$date1."
UNI ON
SEL ECT ra99.sp101,
ra99.sp102 * CASE WHEN ra99.debkred=1 THEN -1 ELSE 1 END
FR OM ra99
WH ERE ra99.date_time_iddoc > ".$date1." and ra99.date_time_iddoc < ".$date2.") reg
INNER JOIN sc33 on sc33.id = reg.sp101
GROUP BY reg.sp101, sc33.descr";
ПоказатьТолько вот у ra99 (Регистр.ОстаткиТоваров) - нет date_time_iddoc.
P.S. Rg99 - РегистрИтоги.ОстаткиТоваров, Sc31 - склады, Sc33 - товары.
(51)
я, конечно, не мог проверить
SEL ECT
t.sp101,
n.descr,
sum(t.sp102) as [sum]
FR OM
(SEL ECT
r.sp101,
r.sp102
FR OM
rg99 as r (nolock)
WHERE
r.period = ".$date1."
UNI ON all
SEL ECT
r.sp101,
r.sp102*(1-2*r.debkred)
FR OM
ra99 as r (nolock)
WH ERE
r.date_time_iddoc > ".$date1."
and ra99.date_time_iddoc < ".$date2."
) t
INNER JOIN sc33 as n(nolock) on(n.id = t.sp101)
GROUP BY
t.sp101,
n.descr
Показатья, конечно, не мог проверить
(51) succub1_5, семерки под рукой нет, все по памяти пишу.
если в ra* нет date_time_iddoc, то
1. там возможно тоже есть поле период, либо
2. нужно ra* inner join _1sjourn on ra*.iddoc = _1sjourn.iddoc and _1sjourn.date_time_iddoc > дата1 and _1sjourn.date_time_iddoc < дата2
если в ra* нет date_time_iddoc, то
1. там возможно тоже есть поле период, либо
2. нужно ra* inner join _1sjourn on ra*.iddoc = _1sjourn.iddoc and _1sjourn.date_time_iddoc > дата1 and _1sjourn.date_time_iddoc < дата2
(4) ture, я по тем примерам и учусь, только что-то не работает =)
Переделал на | $РегистрОстатки.ОстаткиТоваров (:ТекущаяДата~,,Склад = :Склад,Товар, Количество) AS ОТ
Теперь ошибка на дату типа неправильный синтаксис около (ДАТА).
По идее мне нужен готовый MSSQL запрос для вставки в php. Поэтому и мучаюсь =). Если сделать РегистрИтоги - то на текущую дату выводит 1 из товаров в количестве = 0, но по факту его 2 шт.
Переделал на | $РегистрОстатки.ОстаткиТоваров (:ТекущаяДата~,,Склад = :Склад,Товар, Количество) AS ОТ
Теперь ошибка на дату типа неправильный синтаксис около (ДАТА).
По идее мне нужен готовый MSSQL запрос для вставки в php. Поэтому и мучаюсь =). Если сделать РегистрИтоги - то на текущую дату выводит 1 из товаров в количестве = 0, но по факту его 2 шт.
Короче, есть правильный подход:
1) взять за уши одинесника
2) ткнуть его моськой в эти запросы и спросить - "это я должен в этом г...не копаться или ты?"
3) пусть вьюхи читабельные сделает к своим таблицам
4) ты по вьюхам построишь запрос как нормальный программист
1) взять за уши одинесника
2) ткнуть его моськой в эти запросы и спросить - "это я должен в этом г...не копаться или ты?"
3) пусть вьюхи читабельные сделает к своим таблицам
4) ты по вьюхам построишь запрос как нормальный программист
пусть настроит хранение итогов помесячно, тогда на начало каждого месяца будут лежать обороты за весь этот месяц (в таблице итогов, итоги лежат)
останется только добавлять или удалять обороты за этот месяц, чтоб получить остаток на определенную дату.
останется только добавлять или удалять обороты за этот месяц, чтоб получить остаток на определенную дату.
(39) это сленг такой "из транзакций"
дело не хитрое - один пишет, а другой сразу читает, не дожидаясь фиксации или отката.
Нечего автору решать... чистые, грязные. Он их блокировать не умеет. Значит будет грязные читать и резервы делать через сайт с задержкой появления в 1С.
Мы тут сами можем ему на решать, еще и правильней может оказаться.
Вам ли не знать?
дело не хитрое - один пишет, а другой сразу читает, не дожидаясь фиксации или отката.
Нечего автору решать... чистые, грязные. Он их блокировать не умеет. Значит будет грязные читать и резервы делать через сайт с задержкой появления в 1С.
Мы тут сами можем ему на решать, еще и правильней может оказаться.
Вам ли не знать?
(41) ture,
(1) succub1_5, что-то я не понял с примером:
|SEL ECT
СпрСклад.НайтиПоКоду(1);;
Вообще, сделай самый примитивный запрос (например, без параметров), а потом добавляй параметры. От простого - к сложному.
А так - что тут гадать, данных все равно не видно.
Ругается на синтаксис - закомменть проблемную строку, смотри, что получится.
дело не хитрое - один пишет, а другой сразу читает, не дожидаясь фиксации или отката.
Ну так ни из каких "транзакций" он ничего не получит. Все запросы SQL - исключительно к базе, и никак иначе.
(1) succub1_5, что-то я не понял с примером:
|SEL ECT
СпрСклад.НайтиПоКоду(1);;
Вообще, сделай самый примитивный запрос (например, без параметров), а потом добавляй параметры. От простого - к сложному.
А так - что тут гадать, данных все равно не видно.
Ругается на синтаксис - закомменть проблемную строку, смотри, что получится.
(44) Транзакция переводит базу из одного "правильного" состояния в другое "правильное" состояние. Я об этом понятие говорю.
SQL сервер сразу пишет в два места - лог транзакции и конечную таблицу (в конец какой-то секции кластеризованного индекса). Запись в таблице остается помечена той транзакцией, в которой пишутся данные. Это позволит потом такие записи убрать, если откатят транзакцию. Хинт/указатель nolock читает по таблице не парясь есть пометка, что транзакция не завершена или нет. Это принято называть грязным чтением.
Я это так понимаю.
SQL сервер сразу пишет в два места - лог транзакции и конечную таблицу (в конец какой-то секции кластеризованного индекса). Запись в таблице остается помечена той транзакцией, в которой пишутся данные. Это позволит потом такие записи убрать, если откатят транзакцию. Хинт/указатель nolock читает по таблице не парясь есть пометка, что транзакция не завершена или нет. Это принято называть грязным чтением.
Я это так понимаю.
(24) ture,
"я б вообще нагнул этого семерышного программера со стороны php"
" - собрал бы остатки на основе оборотов и без хинтов на таблицы,"
" чтоб взвесить его вотчину по самый не горюй."
я б вообще нагнул этого семерышного программера со стороны php - собрал бы остатки на основе оборотов и без хинтов на таблицы, чтоб взвесить его вотчину по самый не горюй.
ничего не понял из фраз:
"я б вообще нагнул этого семерышного программера со стороны php"
" - собрал бы остатки на основе оборотов и без хинтов на таблицы,"
" чтоб взвесить его вотчину по самый не горюй."
Я так понял вам нужны остатки во внешнюю программу получить, и скорее всего на какой-то интернет магазин. Поэтому как я предполагаю вам нужны только актуальные остатки. Если это так, и вам нужны только остатки на точку актуальности то для этого не надо использовать виртуальную таблицу. Достаточно данных из таблицы итогов. В этом случае запрос будет выглядеть приблизительно так:
Агрегат можно и не ставить если вы уверены, что у вас у регистра только 2 измерения товар и склад.
Отмечу что переменная ДатаТА - это дата начала периода хранения итогов. Обычно это начало месяца текущего периода.
Код |
---|
SEL ECT
$ОТ.Товар AS Товар,
$ОТ.Склад AS Склад,
SUM($ОТ.Количество) AS Остаток
FR OM
$Регистр.ОстаткиТовара AS ОТ (NOLOCK)
WHERE
ОТ.Period = :ДатаТА AND
$ОТ.Товар IN (SELECT VAL FR OM #СписокТоваров) AND
$ОТ.Склад = :Склад
GROUP BY
$ОТ.Товар, $ОТ.Склад
Показать полностью |
Агрегат можно и не ставить если вы уверены, что у вас у регистра только 2 измерения товар и склад.
Отмечу что переменная ДатаТА - это дата начала периода хранения итогов. Обычно это начало месяца текущего периода.
(47) succub1_5, В таблице итогов хранятся итоги на конец периода. Если у вас в 1с-ке для регистров остатков установлен период месяц, то итоги будут хранится на 1-ое число каждого месяца. А то что у вас не правильно показывает в запросе, то это либо вы не тот период указали, либо агрегат забыли поставить. Для получения актуальных итогов не нужно использовать таблицу движений.
А нужно взять остаток из таблицы итогов на нужный период с нужными значениями отборов по измерениям и не забудьте про SUM.
И вообще неплохо бы описание регистра увидеть. Какие там измерения в нем.
Ну и в догонку. Если хотите увидеть поле Date_Time_IDDoc в таблице движений, то нужно зайти в конфигуратор, и установить для регистра признак, "Быстрая обработка движений". Когда это сделаете то увидите поле Date_Time_IDDoc в таблице RA.
А нужно взять остаток из таблицы итогов на нужный период с нужными значениями отборов по измерениям и не забудьте про SUM.
И вообще неплохо бы описание регистра увидеть. Какие там измерения в нем.
Ну и в догонку. Если хотите увидеть поле Date_Time_IDDoc в таблице движений, то нужно зайти в конфигуратор, и установить для регистра признак, "Быстрая обработка движений". Когда это сделаете то увидите поле Date_Time_IDDoc в таблице RA.
Всем спасибо за помощь, в общем сделал так:
то что ниже, так было сперва, потом оказалось что запрос равносилен последнему упрощенному варианту =)
$query1 = "SEL ECT rg99.sp102
FR OM rg99
INNER JOIN sc31
ON sc31.ID = rg99.sp100
INNER JOIN sc33
ON sc33.ID = rg99.sp101
WHERE sc31.CODE=".$mag."
AND sc33.CODE=".$kod."
AND rg99.period = '".$date0."'";
Показатьто что ниже, так было сперва, потом оказалось что запрос равносилен последнему упрощенному варианту =)
//$query = "SEL ECT reg.sp100,
// reg.sp101,
// sum(reg.sp102)
// FR OM
// (
// SELECT rg99.sp100, rg99.sp101, rg99.sp102
// FR OM rg99 (NOLOCK)
// WH ERE rg99.period = '".$date0."'".
//
// UNI ON ALL
//
// SEL ECT ra99.sp100, ra99.sp101,
// ra99.sp102 * CASE WHEN ra99.debkred=1 THEN -1 ELSE 1 END
// FR OM ra99 (NOLOCK)
// INNER JOIN _1sjourn ON ra99.iddoc = _1sjourn.iddoc"."
// AND left(_1sjourn.date_time_iddoc,8) > ".$date1."
// AND left(_1sjourn.date_time_iddoc,8) <= ".$date2."
// ") reg
//
// INNER JOIN sc31 (NOLOCK) on sc31.id = reg.sp100
// INNER JOIN sc33 (NOLOCK) on sc33.id = reg.sp101
//
// WH ERE sc31.CODE=".$mag." AND sc33.CODE =".$kod."
// GROUP BY reg.sp100, reg.sp101";
Показать
(65) succub1_5, если уж упрощать, то так:
что бы избавиться от наложения условий уже после джойнов.
Хотя, возможно, скуль сам оптимизирует.
И да, если нужны текущие остатки, то их действительно можно брать просто по последнему period из rg*.
$query1 = "SEL ECT rg99.sp102
FR OM rg99
WHERE rg99.sp100 in (sel ect id fr om sc31 wh ere CODE=".$mag.")
AND
rg99.sp101 in (select id fr om sc33 wh ere CODE=".$kod.")
AND
rg99.period = '".$date0."'";
что бы избавиться от наложения условий уже после джойнов.
Хотя, возможно, скуль сам оптимизирует.
И да, если нужны текущие остатки, то их действительно можно брать просто по последнему period из rg*.
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот