<?php // Полная загрузка сервисных книжек, создан 2024-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='\
Моя обычная реакция на публикации Маэстро — посмотрел, почесал репу, плюсанул и пошел дальше )))
Выглядит весьма круто =)
Фундаментально выглядит. Но нафига? Никогда не понимал, зачем это нужно.
Запрос оперирует данными, нужно красивое представление — для этого есть другие механизмы.
а без значащихся нулей перед числами можно соорудить?
(5) break, можно, если интерес не праздный. Приведите пример практической задачи — сделаю.
А попроще. Может быть когда-нибудь и 1с это реализует
Большое спасибо за идею использования функции СЕКУНДА для получения остатка от деления. (Кажется мне, что простая проверка четности и другой кратности в запросе надобна чаще, чем перевод числа в строку.)
8 Как раз Вы не правы, чаще перевод даты в строку
На статьи автора у меня тоже реакция одна — почитал, плюс, порадовался, что есть люди с фундаментальным образованием. Сам бы ни за что не написал.
Я правильно понимаю, что строки полученные Вашим методом, потом можно складывать?
Потому что такой вот запрос вернет число как строку неограниченной длины
(11) monkbest, да, можно складывать.
В вашем запросе «представление» это строка, которая формируется не в СУБД, а платформой в процессе постобработки запроса. Также как «итоги», например. Поэтому «представление» вы никак в самом запросе далее использовать не можете.
А строки, полученные в приведенных выражениях, можно использовать в запросе дальше. По ним можно группировать, соединять и прочее. Это обычное выражение языка запросов, хотя и несколько громоздкое.
(12)
так то в принципе и 1С запросы — не чисто SQL запросы, а реляционно-подобные «объектные запросы к ВИРТУАЛЬНОЙ объектной модели»…
т.е. в процессе выполнения такого «объектного запроса» — генирится много дополнительного SQL кода для получения этих объектов..
К чему я это пишу — к тому что повальное увлечение переноса абсолютно всего кода в «1С запрос» — совсем не всегда оправдано на платформе «1С». На практике часто бывает быстрей отрабатывает(и пишется..) код с циклами с использованием 1С объектов «ТаблицаЗначений» и т.д.
(13) sanfoto, я противник крайностей. «Повальным увлечениям» стараюсь не поддаваться. Всегда нужно сравнивать время решения задачи запросом и кодом. Но, чтобы сравнивать решения, нужно их иметь. Вот тут и приведено возможное решение в запросе. Не чтобы безусловно использовать, а чтобы сравнить и выбрать. Таким образом у нас расширяется пространство возможностей, а уж выбор каждый делает сам в зависимости от конкретной задачи.
(15) alex_4x, картинку сами рисовали (редактировали) или взяли откуда?
(16) Это Дилберт! Они очень наслышаны о нашей 1С 🙂
Связываться с датами для усечения дробной части? не накладно?
Может попробовать функцию Выразить(&Число-0.49 как Число(15,0)) ?
(18) Serj1C, в этом случае у меня получалось более громоздкое выражение. Поскольку для выделения одной цифры целое нужно было находить дважды. А по затратам времени, думаю, результаты должны быть примерно одинаковыми. То есть при примерно равных затратах времени выбираем меньшую громоздкость. Такое обоснование.
Пригодился этот метод для таблиц из внешней БД.
Заметил один момент: в десятках выводились значения на единицу больше (например, вместо значения «10307» выводилось «10317»).
Проблема решилась после того, как убрал «+1» из «/ 6 + 1» в вычислении десятков. Вот фрагмент:
Так что лучше перепроверить перед использованием этого метода.
Но мне все-равно очень пригодилось, спасибо.
(20) Sgeor, в тексте метода, приведенном в статье, никакого ВЫРАЗИТЬ нет. Этот оператор в этом случае не нужен, он лишний. То, что написано в (20) у меня совсем никак не работает.
Если же записать в точности так, как написано в статье:
Показать
то результат будет совершенно верный: «10307»
(21) не при чем тут вообще «ВЫРАЗИТЬ» — это кусок давнишнего изврата и мракобесия=)
Тем не менее, я залез уже в консоль перепроверить и на сей раз вбил все чисто:
Результат:
До—-|—После
10300 | 10300
10301 | 10301
10302 | 10302
10303 | 10303
10304 | 10304
10305 | 10315
10306 | 10316
10307 | 10317
10308 | 10318
10309 | 10319
В итоге, если число в предыдущем разряде > 4, то прибавляется ненужная 1. Когда избавился от «+1» в вычислении десятков, все встало на свои места. Когда избавился от «+1» во всех разрядах, снова получил бред. А по твоему коду в (21) все в порядке. Магия.
Думается, что с ID-шниками в базе что-то странное? Нет — число как число.
(22) Sgeor, я, кажется, понял в чем дело. Есть правило определение точности результатов арифметических операций в запросе в зависимости от точности операндов. Они описаны в статье:Разрядность результатов выражений и агрегатных функций в языке запросов . Видимо, срабатывание этого правила приводит к необходимости привести результат customfieldoption.ID * 0.6 к целому типу! В результате производится не отбрасывание дробной части (как задумано в данном в статье выражении), а округление. Поэтому, видимо, нужно предварительно привести операнд к нужному типу, например, ВЫРАЗИТЬ(Id КАК Число(15, 1)).
Добрый день. В базах на sql этот запрос нормально отрабатывает, а в базе на постгри — вылетает с ошибкой. Причем даже если делаю ПОДСТРОКА(«»0123456789″», ВЫРАЗИТЬ(СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, &Число * 0.06)) / 6 + 0.5 КАК ЧИСЛО(1, 0)), 1) (+0.5 использую, так как ВЫРАЗИТЬ округляет число, а не отбрасывает дробную часть)
как этому можно помочь?
(24) selenat, а платформа какая? Вообще с Postgre проблемы могут быть, буду разбираться, но быстро не обещаю.
Платформа 8.3.6.2237
Не могу сообразить, как имея таблицу дат в запросе и вот этот запрос
Показать
получить таблицу дат в строковом выражении?
(27) olbu, вам нужно написать запрос примерно такого вида:
Другими словами, в том поле, где требуется строковое представление даты, требуется записать сложное выражение из статьи, где вместо параметра &Дата указать имя поля таблицы, из которой выбираются даты.
ПОДСТРОКА(«01020304050607080910111213141516171819202122232425262728293 031″,ДЕНЬ(&Дата)*2-1,2)+».»
+ПОДСТРОКА(«010203040506070809101112″,МЕСЯЦ(&Дата)*2-1,2)+».201″
+ПОДСТРОКА(«0123456789»,ГОД(&Дата)-2010+1,1) КАК СтрДата
// Тоже не ахти но …
(29) user633312_i_vi, хороший вариант. С месяцами вообще все хорошо, с годом — плохо.Дни — зависит от вкуса. Лично мне нравится. Возможно, стоит комбинировать в одном выражении оба этих подхода.
Интересный вариант
Гениально!
(3) ну вот увлекается он этим 🙂
если бы в 1с-ком языке появился pl/sql с хранимыми процедурами то наверно все было по другому
При разрядности числа 10 знаков, 3 после запятой
выдает пустую строку.
Из-за того, что получается слишком большое число &Число * 6000.
Этот момент уже разбирался, но я не смог найти где.
(34) Конечно, у «добавить к дате» есть ограничения на величину параметров. И &Число * 6000 не может быть слишком большим. Можно проверить, ограничение порядка 2#k8SjZc9Dxk32, то есть четырехбайтовое целое.
Это ограничение приведенного приема.
В этом случае предлагается выделять младшую и старшую часть числа и переводить их по отдельности.
СтаршаяЧасть = ВЫРАЗИТЬ(&Число / 10000000, КАК Число(15, 0));
МладшаяЧасть = &Число — СтаршаяЧасть * 10000000.
Об этом написано в самой статье
(35) В (23) Вы уже объясняли этот момент, но я не понял. В (35) гораздо понятнее. Мож еще кому понятнее будет. Спасибо.
Добрый день,
если не ошибаюсь ЧИСЛО(8, 2) это 123456.78,
а не 12345678,90
предложение
«» надо исправить на ЧИСЛО(10,2)
(37) Спасибо за уточнение, поправил.
Расширив вариант (29) можно прийти к следующему:
Показать
Используя одну констатнту можно переводить годы в интервале 100 лет (в примере с 1950 по 2049), месяцы, дни, часы, минуты и секунды.
Идея интересная, но… Не дай бог встретить подобное в промышленной БД *представил, перекрестился и плюнул три раза через плечо*
(3) Согласен.
(41)
И я с полпути повернула вспять.
С тех пор все тянутся предо мною кривые, глухие окольные тропы…
Вот как приходится изголяться 1Сникам, только потому что 1С не включила поддержку CAST.
(5)
Показать
Интересно что в Postgre получаю неверный год. Вместо 2018 — 2028.
(45) А что получается, если просто
(46)
2018
(43) что самое интересное, на 8.0, до 2-3 релиза он был и вполне себе работал.
Ага, дошло, долго понять не мог «что функция СЕКУНДА фактически является функцией остатка от деления на 60 числа секунд»,
как понял, все стало понятно.
Попробовал последний запрос на PostgreSql (linux). Как и писалось выше работает некорректно, видимо из-за округления или характерного для этой субд механизма получения дат. Это ни в коем случае не попытка «обхаить». Будьте бдительны с PostgreSQL.
(4) плюсую… как гимнастике ума не более. Инога этим сам страдаю. Но на самом деле вредная статья. Поясню:
Приведен перечень ссылок на вопросы, но вопросы эти ползут от … непонимания — не так ли?
Сам на первых этапах при переходе от скуля и ора (с,паскаль) задавал сначала такие. На самом деле есть два мощных серврера СУБД и 1С, которые надо полномасштабно использовать. Не передавая на СУБД те задачи, которые ей не предназначены.
Пример:
В одной из конфигураций ( разработка внутренняя ) для ведения административно хозяйственной деятельности банка весь расчет амортизации ОС перенесли на запрос. А зачем спрашиваю? СУБД для 1С в основном служит для быстрого поиска… хранения данных и т.д. Все расширения типа pl/sql по сути реализованы в языке … сервера приложений 1С. Кластер СУБД , им рулят его админы, и кластер 1С — оба мощные вычислительные комплексы. Сервер приложений 1С это тоже мощная машина с огромными ресурсами, которые надо использовать. Оптимизация состоит в том, чтобы с клиента один раз обратиться к серверу приложений 1С, с него за раз получить данные из субд и вернуть обратно через сервер приложений 1С на клиента. Опустил пока вопрос записи — объектная модель конечно по сравнению с табличной проигрывает, но зато взаимное поведение объектов относительно друг друга всегда предсказуемо.
Не надо кластер СУБД нагружать ему не предназначенными задачами — надо их верно перераспределять между кластерами СУБД и 1С.
Вы согласны с тем, что все эти переводы из строки туда обратно грамотно реализовать на сервере приложений 1С?
Спасибо! Мне пригодилось.
(6) Практический пример: Есть данные о неких внутренних идентификаторах номенклатуры, приведенных в справочнике с реквизитами «Номенклатура»(Справочник-номенклатура) и «Идентификатор»(Число).
Пример записи:
Маршрутизатор 12345678
Есть запись справочника «Номенклатура» введенная вручную, вида:
«Маршрутизатор 12345678 ПонятияНеИмеюЗачемЭтиЦифры».
Задача: заполнить некий регистр, хранящий записи о соответствиях этих 2х записей.
А вот возник вопрос: а как теперь из получившейся строки убрать лидирующие нули? Мне, например, нужен диапазон какой-то, который я вычислил. В итоге он может быть от какого-нить нуля до какого-нить миллиона, но выводить «00000001-1000000» — как-то некошерно, однако. Есть мысли на эту тему? Первое, что приходит в голову — это поиск минимального «ненуля» и подстрока от позиции ненуля до конца строки. Остается придумать, как оптимально найти первый ненуль.
Спасибо автору поста, очень помогли
ВЫБРАТЬ
ВЫБОР
КОГДА Не ПОДСТРОКА(&Номер, 1, 1) = «0» ТОГДА ПОДСТРОКА(&Номер, 1, 10)
КОГДА Не ПОДСТРОКА(&Номер, 2, 1) = «0» ТОГДА ПОДСТРОКА(&Номер, 2, 9)
КОГДА Не ПОДСТРОКА(&Номер, 3, 1) = «0» ТОГДА ПОДСТРОКА(&Номер, 3, 8)
КОГДА Не ПОДСТРОКА(&Номер, 4, 1) = «0» ТОГДА ПОДСТРОКА(&Номер, 4, 7)
КОГДА Не ПОДСТРОКА(&Номер, 5, 1) = «0» ТОГДА ПОДСТРОКА(&Номер, 5, 6)
КОГДА Не ПОДСТРОКА(&Номер, 6, 1) = «0» ТОГДА ПОДСТРОКА(&Номер, 6, 5)
КОГДА Не ПОДСТРОКА(&Номер, 7, 1) = «0» ТОГДА ПОДСТРОКА(&Номер, 7, 4)
КОГДА Не ПОДСТРОКА(&Номер, 8, 1) = «0» ТОГДА ПОДСТРОКА(&Номер, 8, 3)
КОГДА Не ПОДСТРОКА(&Номер, 9, 1) = «0» ТОГДА ПОДСТРОКА(&Номер, 9, 2)
Иначе ПОДСТРОКА(&Номер, 10, 1)
КОНЕЦ КАК СтрокаБезЛидирующихНулей
Запрос 1С округляет по математическим правилам. Поэтому, представленный перевод из даты в строку не всегда отрабатывает корректно. Пример: 29.08.1995
Добавил немного, чтобы округления возвращали необходимые значения.
ПОДСТРОКА(«0123456789», ДЕНЬ(&Дата) / 10 + 0.5, 1),
ПОДСТРОКА(«0123456789», СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, 6 * ДЕНЬ(&Дата))) / 6 + 0.5, 1),
«/»,
ПОДСТРОКА(«0123456789», МЕСЯЦ(&Дата) / 10 + 0.5, 1),
ПОДСТРОКА(«0123456789», СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, 6 * МЕСЯЦ(&Дата))) / 6 + 0.5, 1),
«/»,
ПОДСТРОКА(«0123456789», ГОД(&Дата) / 1000 + 0.5, 1),
ПОДСТРОКА(«0123456789», СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, ГОД(&Дата) * 0.06 — 0.5)) / 6 + 0.5, 1),
ПОДСТРОКА(«0123456789», СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, ГОД(&Дата) * 0.6 — 0.5)) / 6 + 0.5, 1),
ПОДСТРОКА(«0123456789», СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, ГОД(&Дата) * 6 — 0.5)) / 6 + 0.5, 1)
Внесу свои пять копеек по преобразованию даты в строку
Показать
(57) Не могу подтвердить.
У меня, наоборот, мой код из статьи дает на примере 29.08.1995 совершенно верный результат, а ваш код дает 28/07/1984 на этих данных.
Нужно разобраться. Принцип округления при составлении запроса учитывался. И запрос тестировался. Правда, не на Постгри.
(59) Хочу разобраться: чем не устроил запрос из статьи? Способ округления я учитывал, когда составлял запрос и тестировал подход, но все может быть…
Какая у вас СУБД? Давайте я протестирую свой подход на ваших данных (нужно немного времени). Вообще я против такой громоздкости, даже если она работает.
(60)
Да, от СУБД, судя по всему, зависит.
В приложении 2 картинки. Одна картинка — серверная база с СУБД Postg, другая картинка — файловая база.
Результаты полностью противоположные.
Публикация скоро 5-и летний юбилей будет праздновать.. а мы до сих пор обкладываемся костылями чтобы преобразовать число или дату в строку. Отстаем, лет на 20
Может я что-то не понимаю, но…
Функция ПРЕДСТАВЛЕНИЕ
Данная функция предназначена для получения строкового представления значения произвольного типа.
Параметр функции – выражение любого типа.
Возвращаемое значение – представление значения, тип СТРОКА.
Результат работы функции не может быть использован внутри других функций, за исключением функции ПРЕДСТАВЛЕНИЕ.
Пример: