<?php // Полная загрузка сервисных книжек, создан 2025-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='\
Глюки и ошибки сайта при создании и редактировании новой публикации
вызывают грусть. И печальные обобщения.
(1) Поставил плюс за внятность изложения. И чуть было не снял за мизантропию 😀
Не снимай ! Я тебя еще повеселю .
Захотелось «внятно» ответить на тягучие разговоры о » жизни без последовательностей » и «отказе от партионного учета».
(3) … хм … прекрасно всем известно … сделать можно всё … как впрочем и оправдать …
…
если меня что-то и интересует то только с точки зрения экономической эффективности … а это как прАвило простота решения, пусть даже и более длинного …
такой же принцип и в массовом производстве … так технологичесие процессы расположены вне логики ручного труда …
…
… вот …
(3) А кто это отказывался от партионного учета? Мы его заклеймим!
А жизнь без последовательностей радостна и безоблачна, и никакого отношения к партионному учету не имеет.
Партионный учет — объективная потребность (а значит, реальность).
Последовательность — химера, рожденная в воспаленных мозгах разработчиков. Последовательности ирреальны, ибо не встречаются в жизни.
К сожалению, в отличие от других нервно-паралитических болезней, эта (использование последовательностей) оказалась заразной. А поскольку из всех лекарств в арсенале восьмерки остались одни запросы…
(5) Арчибальд , ты , конечно, кавалер авторитетный и всё такое…
Но :
«Потребность = реальность»,
«последовательность = химера»
— э..э .. перехвалили тебя .
В «восьмерке» не остались , а добавились запросы как признание столбовой дороги развития СУБД . Представленный алгоритм как раз и говорит :
авторитетному мужчине пора завязывать с 77.
поправь ссылочку в конце и на статью Шепота ещё можно сослаться.
(7) Поправил. И Шепоту досталось.
(8)http://infostart.ru/public/61745/
(10) В указанных ссылках у Шепота приводится понимание Шепотом нарастающих итогов и ни слова про их эффективное вычисление.
(11) но там примерно так же описан пример для получения этих самых нарастающих итогов.
существует множество разных языков … все они что делаю хорошо а что-то плохо …
язык запросов существует для получения копий таблиц + фильтрация из БД …
пытаться программировать, манипулировать данными на уровни запросов — утопия … и СКД это наглядно демонстрирует … Запрос+ТЗ = универсально, практично, феерично …
запрос + тз = неограниченные возможности в манипулировании данными … быстрота в объединении этих возможностей а не в их пересечениях … вот …
… понятно, как задача для ума может это и интересно … но не более …
… вот …
(13) Черт возьми , стал бы я практиковаться «для ума » !
В настоящий момент я считаю такую процедуру самым быстрым и эффекивным способом получения всех движений по регистру партий (читай- перепроведения документов по регистру партий).
Нужна ,конечно, тестовая конфигурация для подтверждения этого мнения. Пока она не представлена.
Шепот , ты упорно не хочешь изучать СКД.
Можно сказать , что в узком смысле СКД = запрос+тз+обработка тз.
Уж за что 1с не должно быть стыдно , так это за СКД.
«пытаться программировать, манипулировать данными на уровни запросов — утопия … и СКД.»
Я не согласен с тобой. Работая в клиент-серверном варианте мы, наоборот, просто обязаны пытаться «программировать, манипулировать данными» при помощи запросов. Для тебя же запросы — средство простой выборки данных, после которой «тыканье кнопок» ,т.е. любимый кодинг.
Скажи, Шепот , тебя убедит что текущий алгоритм не баловство «для ума » если в рамках рассматриваемой конфигурации ты получишь по сравнению с обычным перепроведением ускорение в сотни раз ?
Ish_2 у меня совершенно нет желания принижать твой труд и его оспаривать … наоборот я им восхищаюсь равно как и трудами anig99 …
.. хм… в сотни раз …. это конечно ты перебрал хотя упорствовать не буду … но я точно знаю что труды ВалерычА (http://infostart.ru/profile/36029/ ) гораздо продуктивнее … он уже добился быстродействия в 100 раз а возможно и более …
также хочется напомнить и про труд Владимира (http://infostart.ru/profile/2905/ ) хотя и в рамках отдельной конфигурации …
… добиваться же быстродействия в рамках запроса …? для меня очень и очень не понятно — для меня это создание исскуственных трудностей на пути поиска простых и эффективных решений …
… соглашусь и с возможной, своей полной или частичной — НЕграмотностью …
… вот …
(15) + забыл … видимо не совсем точно написал : СКД как раз и демонстрирует что Запрос+ТЗ есть сила …
… вот …
(15) Шепот , принижай мой труд ! Разрешаю.
Но убедительно — с аргументами.
Представь себе , что я внимательно читаю и проверяю ,что ты мне написал.
Ссылки на Валерыча и Владимира не убеждают .
Они рассматривали совсем другие темы.
(17) … уж нет … увольте Вас убеждать, Вас — это ваше поколение … мне хвататет этого удовольствия и в жизни … ваш молодЁжный бег по кругу меня никак не интересует …
в 1С запрос это только «чтение» … запись не возможна … любые операции с данными гораздо проще делать в таблицах, массивах ….
… я сам закрываю 26 счет, для подсчёта нулевой рентабельности, нууу это типа точкаБЕЗубыточности … 3 разными способами … прекрасно знаю что 1С механизмы очень долгие и добиться увеличения быстродействия на порядок, заменив их на свои, это почти без проблем ….
ссылки на ВалерычА и Владимира считаю основными … так как эти товарищи прекрасно демонстрирует силу самостоятельного программирования … не умаляя 1С как сверхУниверсальную систему …
… ВОТ …
(17) спорить конечно бесПолезно т.к. рано или поздно все приходит к записи таблицы … нууу, например у тебя: «…Полученную таблицу движений можно или «подокументно» записать в регистр партий или предварительно сравнить с существующими движениями в регистре и записать только «изменения». …»
… по сути, мы пропагандируем одно и то же решение — оптимально, 1С часто это делает неЭффективно из-за своей гиперУниверсальности, любыми доступными методами собрать данные в таблицу и записать её … здесь мы едины … просто я считаю что запрос для оперирования данными не эффективен а ты считаешь наоборот … вот …
(19) Говорю тебе : молодое поколоние выбирает запросы . И осуждает Шепота.
За что ? А вот за это :
1. «… добиваться же быстродействия в рамках запроса …? для меня очень и очень не понятно»
2. «просто я считаю что запрос для оперирования данными не эффективен..»
Запрос бывает эффективен или неэффективен не вообще , а для конкретной задачи.
Если тестирование показывает , что запрос работает быстрее ,чем кодинг — то запрос эффективен. Настоящая тема как раз о том , что , по мнению автора, запрос эффективнее для задачи перепроведения документов , чем кодинг. Разумеется , только для текущей простейшей конфигурации.
Для других конфигураций нужно проводить конкретное тестирование и приведенный в статье алгоритм лишь отправная точка для создания эффективного решения.
(13) язык запросов 1с может и существует только для получения информации, но в БД в чистом виде всё основывается на этих запросах и их быстродействии. Если посмотреть на работы по анализу производительности Гилёва, то основа у него — разбор запросов к СУБД генерируемых платформой 1с. Если всё сводилось только к кодингу в классическом смысле, то можно было бы продолжать работать с файлами с текстовом формате. БД и были придуманы для ускорения работы с чтением и записью в огромных массивах данных. А основной язык общения с СУБД — это запросы. И чем больше объем данных, тем более эффективным является правильно построенный запрос в правильно созданной БД по сравнению с обработкой кодом.
Естественно, запросный подход не идеален (а уж тем более запросный 2го уровня, когда запрос «транслируется» в родной язык БД), в частности, с учетом нарастающих итогов… Поэтому нужно соизмерять важность скорости получения результата и сложность достижения этой скорости. Поэтому поводу — пусть 1с самый простой и самый долгий — «перепровести всё нах» или какой-то, видимо, относительно простой, но ОЧЕНЬ долгий алгоритм примененный в документе «корректировка стоимости партий» (у меня он идет 7 часов! а результирующих движений 3000-7000 тыс на регистр, т.е. большую часть времени происходят именно расчеты). Второй путь — код и много мелких запросов — сейчас я его использую и проверка Fifo хоть и занимает несколько часов, но всё же меньше, чем проведение по партиям. 3ий неизвестный по поведению относительно производительности — расчет в одном сложном и оптимизированном запросе.
(21) Конечно.
Нужно только пробовать на твоей конфигурации , чтобы убедиться что эффективнее.
Меня смущает составное поле в условиях соединения — МоментВремени.
Индекировать врем.таблицу по нему нельзя. Означает ли это , что оптимизатор запроса будет сканировать не индекс , а основную таблицу — что приведет к замедлению ?
(22) Сделай 2 поля Период и МоментВремени. Период точно можно проиндексировать.
Запросы в статье можнораскрасить получше 🙂
(24) Возможно, нужно раскрасить по-приличней.
Но мы с Шепотом как-то всё по-дедовски , да по-старинке ….
(23) Но тогда в условии соединения вместо
НарРасход.МоментВремени > НарПриход.МоментВремени
придется написать
НарРасход.Период> НарПриход.Период ИЛИ
НарРасход.Период = НарПриход.Период И
НарРасход.Регистратор > НарПриход.Партия
Насколько мне известно, оптимизатор запроса если в условии соединения есть «ИЛИ»
вынужден сканировать не индекс , а основную таблицу. Что тоже не есть хорошо, т.к.
таблицы НарПриход и НарРасход могут быть очень большого размера.
(26) Вот без ИЛИ
НарРасход.Период > НарПриход.Период И
НарРасход.МоментВремени > НарПриход.МоментВремени
(27) Не понял. В твоем выражении
«НарРасход.Период>НарПриход.Период» — лишнее условие.
Потому что из «НарРасход.МоментВремени > НарПриход.МоментВремени » совершенно очевидно следует «НарРасход.Период>=НарПриход.Период».
И оптимизатор запроса всё равно будет проверять условие по Моменту времени.
В чем выигрыш ?
(27) Редактирование поста (28) , судя по всему невозможно. В нем ошибка.
Мне непонятен смысл : зачем добавлять еще одно выражение , т.е.
«НарРасход.Период > НарПриход.Период »
если оптимизатор запроса всё равно будет проверять неиндексируемое поле МоментВремени в
«НарРасход.МоментВремени > НарПриход.МоментВремени»
В чем выигрыш ?
В том, что во временной таблице его можно проиндексировать.
(30) Мда… Браво !
Действительно, МоментВремени НЕЛЬЗЯ влючать в индекс в основных таблицах и МОЖНО Включать в индекс во временной таблице.
(22) Могу сделать следующий, на первый взгляд парадоксальный вывод:
сравнение
НарРасход.МоментВремени > НарПриход.МоментВремени
в Вашем запросе НЕ ТРЕБУЕТСЯ!!!
Эта логическая ошибка поясняется схемой в файле (рис.2). Кстати, схема, поясняет и сущность метода. На словах дело в том, что проверка нужна, чтобы избежать списаний «по-красному». Но если Вы вырезаете их такой проверкой, то почему не уменьшаете на сумму вырезанных списаний накопленный расход?
Выход в том, чтобы списывать по-красному (тогда проверка не нужна!), либо делать третий накопленный расход (запрос будет другим)
(32) Попытаюсь понять. Завтра.
Странно, но рисунки перед опубликованием рисовал до смешного похожие на Ваши .
Хотя, возможно, это единственный наглядный способ отображения сути соединения по двойному неравенству.
Теперь о грустном…
Оценка трудоемкости запросов 1, 2 и 3 приводит к формуле
O(n * n / 2) + O(m * m / 2) + O(n * m / 2),
где n — число приходов, m — число расходов. Оценка обосновывается
http://infostart.ru/public/61295/ изменит оценку на следующую
методом «вложенных циклов», который используется при оптимизации запросов.
Действительно, для каждого прихода в запросе 1, например, требуется просуммировать
в среднем n / 2 записей (при использовании индекса по моменту времени). То есть,
трудоемкость пропорциональна квадрату числа приходов (расходов для запроса 2).
Ускорение по методу
O(n * ln(n)) + O(m * ln(m)) + O(n * m / 2),
что, конечно, гораздо лучше, но при наличии процедурных подходов с трудоемкостью
O(n + m),
не требующих дополнительной памяти
(а в Вашем случае хранится и обновляется примерно log(n) уровней итогов),
преимуществ метода «одного запроса» не усматривается.
Вас мог смутить реальный выигрыш по быстродействию метода
http://infostart.ru/public/61295/ в задаче просроченной задолжности.
Но там не было внешнего цикла! Там был переход от пропорции O(n) к пропорции O(ln(n)),
что существенно. В задаче ФИФО есть внешний цикл — задачу накопления нужно решить для каждой накладной.
И это все меняет.
Не знаю, можно ли надеяться, что 1С в своей обертке SQL даст нам возможность быстрого нахождения тэта-соединений таблиц
(такие вопросы ставились) или функцию нарастающих итогов. Сейчас 1С стыкуется с разными СУБД, возможно, будут какие-то находки.
Взять, к примеру, агрегаты в 8.2.
Но пока встроенных нарастающих итогов в запросах нет и компромиссом будут процедурные решения. 😥
Кстати, похожий вопрос обсуждался здесь:
http://www.sql.ru/forum/actualthread.aspx?bid=1&tid=113703&pg=1
А вот что, нельзя было 3-5 предложениями описать ИДЕЙНУЮ суть алгоритма?
(35) Возможно, ты прав.
Но я побоялся рисовать что-то подобное рисунку в (32). Подумал что это не облегчит понимание , а еще больше запутает.
(36) … за одного битого — двух не-битых дают … вот …
После набора длинного ответа на (32) — ошибка сайта.
Регулярные глюки сайта просто бесят.
(38) … ИС — бегая за «формой» однозначно теряет в «содержании» … вот …
(32) Не согласен.
Строка в условии соединения
«НарРасход.МоментВремени > НарПриход.МоментВремени »
совершенно необходима.
Если это условие убрать , то более ранний расход «спокойно» спишется с более позднего прихода.
Как мы тогда в выходной таблице отловим эту ошибочную ситуацию ?
Компромиссом следует считать следующий подход :
Строка
«НарРасход.МоментВремени > НарПриход.МоментВремени » из условий соединения убирается.
А в поля выборки добавляется строка
«Выбор Когда НарРасход.МоментВремени > НарПриход.МоментВремени
Тогда Истина
Иначе Ложь
Конец как ПризнакСвоевременности»
Тогда появляется возможность «отловить» в входной таблице эту ошибочную ситуацию.
Поэтому предложение просто убрать строку
«НарРасход.МоментВремени > НарПриход.МоментВремени »
из условий соединения нельзя назвать верным.
А в файле СписаниеПоМетодуФИФО.dt применено ЛЕВОЕ СОЕДИНЕНИЕ.
С обработкой значений NULL.
(38) За одного бита дают 1/8 байта 😎
(34) Теперь о грустном :
К сожалению ,оценку трудоёмкости вычислений я забыл. Поэтому о верности приведенных формул мне судить трудно.
Но и без формул понятно , что количество вычислений в текущем алгоритме больше , чем при «процедурном подходе».
Разумеется , приведенный в теме алгоритм с эффективным вычислением нар.итогов многократно выиграет у простого перепроведения расходных документов ,если в каждом расходном документе предусмотрен запрос к остаткам регистра партий.
Но Ваш пост , как я понял, о другом . Из него вытекает :
Для исходных таблиц значений Приход и Расход можно привести такой кодинг с циклами («процедурный подход») , реализующий метод ФИФО , который многократно
превзойдет текущий алгоритм с любым самым эффективным вычислением нарастающих итогов . При этом размер таблиц Приход и Расход может быть как угодно большим .
Так ?
(40) Да, правильно, если проверка и нужна, то только для вычислений «ПризнакСвоевременности», а не для отбора записей в соединяемой таблице. При этом индекс по МоментВремени не нужен.
А вот левое соединение и обработка NULL — это неправильно, так как если расход не сделан, то следующие «своевременные» расходы должны соединяться с приходами, пропущенными в паре с несвоевременными расходами.
(42) Да, так. Причем для Вашего «модельного» случая код занимает один — два десятка строк.
Для каждой значения Номенклатуры из таблицы НарРасход мы строим движения по регистру партий.
Поэтому если N-расход по M-номенклатуре получился «красным» , то зачем нам последующие «своевременные» расходы N+1,N+2 и т.д. по M-номенклатуре ?
Совершенно очевидно , что они не имеют смысла .
Для М+1-номенклатуры , конечно, будет выстроена своя последовательность движений расходов. Как и для M+2,M+3 и т.д.
Вот почему утверждение в приведенной цитате — неверно.
Тем более если в таблице НарРасход для М-номенклатуры имеются записи со значением поля КоличествоДо больше любого КоличествоПосле в таблице НарПриход эта запись при ВНУТРЕННЕМ СОЕДИНЕНИИ просто «пропадёт» в выходной таблице «без следов».
При ЛЕВОМ СОЕДИНЕНИИ мы достигаем того, что в выходной таблице гарантировано будут присутсвовать все регистраторы-расходы. И по полям признакам мы сможеи определить какое движение регистратор — неверное (или «красное»).
(44) Согласен.
(45) Не буду занудой и соглашусь, так как речь идет о реакции на ошибку пользователя. А это, в общем-то, дело вкуса. Как в анекдоте про тараканов — неважно утонут они или подорвутся на минах 😀
(47) Ну и заканчивая , можно сказать :
т.к. в рамках рассматриваемой простейшей конфигурации «запросный» метод значительно уступит по быстродействию «процедурному подходу» (т.е. «вручную» просканировать две исходные таблицы Приход и Расход для получения движений),
то единственной , достойной внимания особенностью представленного алгоритма является перенос в трехзвенной системе( клиент-сервер приложений- сервер БД) всех вычислений на сервер БД.
Все в одном запросе это конечно хорошо, но пока больше походит на то, что 1С из инструментов дала только вилку, и для поедания супа приходиться изголятся и пытаться сложить ложку из кучи вилок. В нормальной БД получение нарастающих итогов легко делается процедурным методом на сервере — обходишь курсор и подбиваешь суммы.
(49) Хоть не палочки бамбуковые 😮
(49) курсор рулит
(49) Я так и не отгадал загадку :
Почему в языке запросов 1с не разрешен Update.
Понятно , что не стоит разрешать Update при обращении к таблицам БД.
Но почему не разрешен Update к временным таблицам хоть убей — не пойму.
(51) Конечно, так. Но по ссылке в (34) нашел цитату Aleks2 на SQL.ru
1) Если у тебя есть возможность не пользоваться курсором — не пользуйся им.
2) Если у тебя НЕТ возможности не пользоваться курсором — ВСЕ РАВНО НЕ ПОЛЬЗУЙСЯ.
————-
Запрос всегда быстрее курсора, единственное исключение: неправильный (неоптимальный) запрос.
В общем случае это ,конечно, неверно. Но уж больно симпатично.
(53)
Ну, опять же на нормальной БД нарастющие итоги на врем-таблицу можно накрутить и без курсора.
(54) Ага,примерно так.
И получается , что наличие в языке запросов Update делает ненужными любые разговоры об эффективном вычислении нарастающих итогов , занимающего
львиную долю времени в текущем алгоритме.
(55)(54)(51)
Логотип темы — «Мы пишем запросы!».
Позволю себе высказаться не в тему.
Для простого и эффективного решения аналогичных задач не требуются:
1) Наличие в языке запросов Update.
2) Временные таблицы.
3) Процедурные методы на сервере.
4) Курсоры.
5) Всякие «левые» и «правые» соединения.
Да и сами запросы не требуются. 😉
Печально, что движение по «столбовой дороги развития СУБД»(с) ведет в тупик. А «круглые колеса, на каких во всем мире принято ездить»(с) ускоряют это движение… 🙁
(56) Хм.. Владимир, Вы упорно отстаиваете свой экстравагантный взгляд на развитие СУБД с отрицанием языка запросов SQL . И ,как обычно, не приводите хотя бы внятного обозначения альтернативного подхода.
Впрочем , однажды Вы в своей теме привели текст кода а-ля Clipper Summer ’87, обозначающий Ваш подход к решению такого рода задач и заставивший меня смахнуть слезу :
do while !eof()
………
enddo
Т.е. сканирование таблицы и ручной кодинг.
Возврашаясь в 1987г , Вы отрицаете ту самую двадцатилетнюю «столбовую» дорогу :
-Утверждение стандарта SQL от 1992г.
-Развитие трехзвенной системы клиент-сервер приложений-сервер БД.
Оно конечно, Вам это никто не запретит. Но думаю , Вы найдете мало сторонников.
Если вдруг на каком -то этапе на «столбовой» дороге откажутся от языка запросов — я первый сниму перед Вами шляпу.
(57)
Игорь.
Я не отрицаю язык запросов в развитии СУБД. Я утверждаю, что для наших задач надо иметь ДВА способа (ЯМД) обработки данных. И в задачах типа «Нарастающие итоги» просматривать таблицы построчно в обычном цикле на стороне клиента. Это быстрее работает, не загружает сервер лишней работой, проще писать ««ручной кодинг»». Есть алгоритмы, где эффективней использовать язык запросов.
А в целом, наличие двух ЯМД позволяет проектировать схему БД не под средства манипулирования данными, а под предметную область. И отпадает необходимость в «трехзвенной» архитектуре, как средства преобразования одного ЯМД в другой.
В дохновляет! 💡
(58) Истина всегда конкретна (с).
Соображения общего плана (58) меня мало в чем убеждают.
Разберемся конкретно .
Мы разбираем задачу вычисления нарастающих итогов в клиент-серверной архитектуре.
Цитататы :
«Для простого и эффетнаективного решения аналогичных задач не требуются:
1..5 . Да и сами запросы не требуются..»
«И в задачах типа «Нарастающие итоги» просматривать таблицы построчно в обычном цикле на стороне клиента. Это быстрее работает, не загружает сервер лишней работой, проще писать ««ручной кодинг»».»
Из этих цитат вытекает , что в клиент-серверной архитектуре для вычисления нарастающих итогов:
1. БОЛЕЕ эффективно загрузить таблицу с сервера на клиента и далее на клиенте ручным кодингом просканировать таблицу в цикле (do while…skip…enddo).
2. МЕНЕЕ эффективно оставить таблицу на сервере и одной командой Update получить таблицу нарастающих итогов см (54)
Так ? Или я что-то напутал ?
Кстати… С одной стороны, обработка на клиенте удобнее… С другой стороны это противоречит концепции тонкого клиента и web интерфейсов. Узкие или загруженные каналы требуют уменьшение объема передаваемой информации. Это раз. Во-вторых, клиентские машины могут быть маломощными не только из-за экономии средств. Нетбуки, наладонники и т.д. имеют возможность работы с 1с, но не могут переваривать огромные объемы информации. Поэтому нужно идти по пути переноса обработки данных с клиентских компьютеров на сервера в любом виде: будь то запрос, или инструкция к компилятору.
(60)
Игорь.
1) Для обработки таблицы навигационным способом не требуется загружать таблицу с сервера на клиент. Выполняется чтение по одной записи. Вычисление и накопление нарастающего итога на клиенте для каждой строки в переменной оперативной памяти. Выводится в отчет строка вместе с вычисленным итогом. Т.е. выполняется чтений столько раз, сколько строк в таблице (обозначим — N).
2) На сервере же формируется рабочая таблица (в простейшем случае N чтений и N записей). Далее читаем каждую строку рабочей таблицы (N чтений), вычисляем нарастающий итог и записываем его в каждую строку (N обновлений). Далее передаём все строки рабочей таблицы клиенту (N чтений). Итого 5*N чтений/записей.
По сети, в обоих способах, предаётся одинаковое количество строк.
(62) Владимир.
Чтение (62) вызвало у меня столько вопросов, что я просто оробел что-то спрашивать.
Допускаю, что моего разумения просто не хватает , чтобы осилить (62).
(63)
Игорь.
Жалко, что Вы принципиально не используете «смайлы».
Сообщение #63 – это шутка?
Или намек на мою дурость?
(64) Намек на мудрость.
Этап III .Особенно — «предварительно сравнить с существующими движениями в регистре и записать только «изменения». А на этом месте можно поподробнее.Будет очень хорошо если дополните конфу.Вам же как Гению Партий!!!.
Пасиба 🙂
(66) Место Гения давно и прочно занято.
Вариант:
1. Мы получили запросом ТаблицуДвижений.
2. Делаем Полное Соединение с движениями из регистра партий.
3. Оставляем в таблице , полученной в п.2, только расхождения , т.е. получаем ТаблицуРасхождений.
4. Затем с помощью запроса
«Выбрать Различные Регистратор ИЗ ТаблицаРасхождений» получаем таблицу -столбец
с документами , которые нужно перепровести.
5. Сканируя таблицу, полученную в п.4, для каждого документа- регистратора выбираем нужные движения из ТаблицыДвижений и записываем их в регистр.
(67)
Кем 😮
(68) Гений 1с , в миру Осипов Сергей.
Об изгнании его с ИС я писал в теме Life «Тошнота как реакция на свободу».
(69) Фуу… А я-то понял, что его место на ИС кто-то занял 😀
(71) Пока нереально.
Если в языке запросов 1с появится Update , Declare , Create Table (для временных таблиц), то представленный алгоритм , на мой взгляд, для больших таблиц выиграет у любого другого.
Это предсположение основывается на том , что
вся тяжесть вычислений в алгоритме ложится на вычисление нарастающих итогов.
С помощью команды Update нарастающие итоги считаются очень быстро.
Два года назад я тоже самое пытался сделать для 7.7 😀 на языке MS SQL, и там есть Update, но его скорость меня не устроила, так как базу проводил за 3 года (FIFO), потом выгружал в динамические таблицы в SQL — тоже тормоза… потом плюнул на все технологии выгрузил данные в txt-файл (10 мин), на Дельфи конвертирую в свой формат (2 мин), записываю (чтобы при следующих запусках не конвертировать по-новой), и делаю расчет по FIFO. База за 3 года проводится за 1 секунду (ОДНУ СЕКУНДУ). Вот и все. Разработка тут:Разработка тут Скоро сделаю внешнюю обработку для 8.1 — выгрузка данных, чтобы можно было проверять 1С — правильно ли она по FIFO считает.
(69) … а я не нашЁл у Вас этой статьи … нельзя ли её где-нибудь и как-нибудь по-читать-то … ? … или дайте пожалуйств ссылку НЕумелым … вот …
(72) согласен с Маньяком. Решение задачи в лоб — это просто жесть.
Вы ждете возможностей языка, которые позволят втиснуть ваши огромные вычисления в рамки приличий по быстродействию? А решение лежит в другой стороне. Смоьтреть надо в сторону изменения структуры регистров, которая позволит анализировать только то, что реально нужно…
(73) В солнечной Анапе , чтобы выйти в интернет на почте нужно предьявить паспорт.
Попросив уже сидевшего за компьютером человека посмотреть ИС , увидел комментарий и побежал за паспортом. Жара , скучно, на море ни ногой — делать нечего.
Как обычно , хмыкну там где восторгается Шепот.
Выгрузки — загрузки в txt, потом в свой формат и т.д, чтобы потом «ЗА ОДНУ СЕКУНДУ» !
— это для кого текст ? Для специалистов ? Если — да , то для каких ?
В статье предлагается общий алгоритм списания по методу ФИФО.
Который может быть реализован как на платформе 1с , так и на другой платформе средствами только TSQL. В последнем случае эффективность реализации алгоритма многократно выше.
( с помощью Update нарастающие итоги считаются быстрее)
(75) Маньяк так Маньяк. Жесть так жесть. Это понятно.
Остальной текст «жестьтоко» загадочен.
кто выдал ишу паспорт?
(76) Привет отдыхающим!! 😉
Выгрузка и загрузка (конвертация) у меня происходят в 3 часа ночи… зато при открытии пользователем мгновенно загружается в динам.массив и идет работа с OLAP (по вчерашний день)….
Метод FIFO на 1С делал применительно к расчету дебиторки / кредиторки, когда считал взаиморасчеты и самое главное кол-во дней просрочки… быстродействия хватило…«Отчеты о просрочке долгов» А вот с партиями — увы нет — 1С это не потянет!!! — точнее база будет проводится столько ко же, как при обычном проведении, ну не 6 часов, а всего 2 часа 🙂 Потом на SQL делал хранимую процедуру метода FIFO — тоже тормоза… ну не может SQL сделать update даже миллиона записей!!!! (поле себестоимость) — не может и все!! select может, а update нет….
В общем то, статья хорошая, все нормально. Метод FIFO, LIFO,… известные. Есть даже метод «списания максимальной себестоимости» (который придумал мой знакомый)… Но мне все же нравится метод FIFO!
Кстати, когда я практически его реализовывал — и при гашение долгов и при гашении партий — выяснилось, что «в чистую» этот метод на практике не применим, и «за один проход» не получается. А причина была в том, до метода FIFO приходится делать первый проход при котором идет гашение с учетом явных ссылок (начиная от сторно, возврат ошибочно перечисленных сумм, возврата товара и других движений….). Вот, что хотелось бы добавить к статье.
(78) 🙂
(78) Вот и ты , Миша, не любишь иша … Как эта тетка на почте :
— Мужчина в желтых трусах ! Я же вам сказала : отойдите от компьютера.
А трусы у меня , Миша, между прочим адидасовские — яркие ,оранжевые.
Адидас, правда, цыганский и кореша говорят , что похож я в них не на голландца ,а на бандеровца. Но они мне нравятся и я их ношу…
— Пустите . Я же в прошлый раз Вам паспорт показывал.
— Мужчина мне нужно внести ваши данные . Вы это понимаете ?
Крыть было нечем и я решился .. перегнувшись через стойку доверительно сообщил:
— Девушка , а трусы на мне не желтые , а померанчевые ! Бачишь ?
Пока она с трудом подбирала ответ я понял , что не попал. Мда… Здесь вам не инфостарт , «штучки-дрючки» не проходят и не дожидаясь ответа ,я поперся за паспортом.
(80) Таки тетка или девушка?
(81) Кавалер к тетке обращается — «девушка!». Не знал ?
(82) Не знал. Сам пользуюсь терминами «сударыня» или «миледи» 😳
Добрый день!
Создал новую публикацию (http://infostart.ru/public/88999/) с возможным альтернативным алгоритмом.
Милости прошу комментировать 🙂
—
С уважением,
Юрий Строжевский
Вопрос, а если приходная накладная сделана со знаком минус? получается она выпадет из последнего запроса а по идее должна скорректировать предыдущие распределения, либо надо все приходы со знаком минус переквалифицировать в расходы со знаком плюс :). Что тоже неправильно 🙂
(85) Приходы с отрицательной суммой в статье не рассматривается.
1. Или нужно дополнительно обрабатывать таблицу приходов , что избавиться от «минусов».
2. Или алгоритм по Фифо должен быть существенно усложнен.
В СКД в вычисляемых полях появилось возможность использовать ВЫЧИСЛИТЬВЫРАЖЕНИЕ(). Лично у меня получилось поделить долг между накладными. Берём остатки по регистру взаиморасчёты, левое соединение на регистраторы регистра взаиморасчёты, сортировка в порядке убывания даты регистратора, группируем по клиенту и договору. + вычисляемое поле. В нём я использовал выражение:
Всё почти хорошо. Однако при использовании дополнительной группировки по степени просроченности долга (долг не просрочен, долг просрочен не более на 5 дней, долг просрочен на срок 5-30 дней и т.д.) вычисляемое поле вычисляется в пределах отдельной группировке по степени просроченности долга, а не в пределах клиента. Подозреваю, что надо «побаловаться» с параметрами ВычислитьВыражение(), но пока не додумал. Может у кого-то получилось понять суть этих параметров. Прошу поделиться идеями, ибо у меня уже мозг закипает.
(87) Вы описали задачу НЕ ФИФО , рассматриваемую в этой теме, а ПросроченныеДолги.
В голову даже не приходило решать эту с помощью выражений СКД.
Впрочем, я еще даже не установил 14 релиз платформы.
(88) простите просматривал все темы по Накопленным итогам. В этой самые последние сообщения. Тем более, что дебиторка использует ЛИФО. Так что принцип, думаю, аналогичный.
Прикольно!
(90) Как общее соображение принимается к сведению.
На мой вкус, только не хватает вывода или утверждения.
Мне другая интересная задача недавно попалась —
Получить таблицу минимальных дозакупок на каждый день месяца для того чтобы вывести в ноль все ежедневные отрицательные остатки задним числом. Пример
Дата Остаток ! Дозакупка НовыйОстаток
01 -3 3 0
02 4 0 7
03 -1 0 6
04 -4 0 2
05 -7 5 0
06 2 0 7
Вот нужно получить колонку Дозакупка.
Естественно хотелось бы решить ее запросом.
(92) Мммм.. неплохо. Создай тему с решением.
Я сыграю «вторым номером», т.е. оппонентом.
P.S. На всякий случай : эффективного решения в данный момент у меня нет.
(92) Впрочем, возвращаясь к твоей задаче, замечу , что такая постановка малопригодна для практического применения. Оформляя доп.приходы по итоговым остаткам на конец дня , мы не учитываем реальную ситуацию,при которой отрицательные остатки могут возникать несколько раз в течение дня .
Конечно , можно решать и твою задачу как некий упрощенный частный случай.
Но для общего случая ( интересен , на мой взгляд именно он) правильно формулировать следующим образом :
Проверить и найти все отрицательные остатки за период возникшие после момента проведения любого расходного документа. Реализовать одним запросом.
Другими словами , на входе имеем таблицы :
НачОстаткиНаНачалоПериода
ВсеПриходыЗаПериод,
ВсеРасходыЗаПериод.
На выходе должны получить таблицу РасходныеДокументыСОтрицательнымиОстатками.
Далее нужен анализ :
или сдвинуть расходный документ во времени в течение дня.
или оформить доп. приход.
Остатки на конец периода должны остаться неизменными.
Таким должен быть , на мой взгляд , подход к решения такой задачи.
Скачал, запускаю на 8.3.9 в Конфигураторе.
Загружает.
Задает вопрос о конвертации.
И после подтверждения сразу в дамп.
Разучилась, видимо, превращать базы на 8.1 в 8.2.
Пришлось искать 8.2 для конвертации и хорошо, что нашел, сконвертировал.
Но оказалось что все еще проще. В окне настройки инф.базы надо поменять с 8.3 на 8.2)
Или пятница, или уже очевидные вещи вылетают из головы)
осциллирующую функцию остатков разложить на сумму монотонно убывающих функций. каждая входящая партия остатков может только убывать. соответсвенно если по партии есть отрицательный остаток — нужно дозакупить этот отрицательный остаток. найти дату по минусовому хвосту — плвеое дело.
(96) CheBurator,
Привет , Чебур. Сколько лет прошло ?
Ты написал что-то умное и серьезное.
После школы, стало быть , еще не забыл про «монотонно убывающие функции».
А я забыл . Но был рад тебя почитать !
Отличный метод!
А LIFO из него никто не делал?
Создал отдельную темку на форуме про LIFO.. если кто знает, помогите плз…
http://forum.infostart.ru/forum9/topic220953/message2246820/#message2246820
(99) Давно это было..Вряд ли помогу.