Минимализмы




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?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='\

82 Comments

  1. trumanl

    Классная подборка, так сказать на «подумать».

    Конечно в реальных задачах не часто этому можно найти применение, но кое-что взял на заметку.

    Спасибо! Люблю читать Ваши статьи.

    Reply
  2. Denis S

    Спасибо за статью! Хорошая пища для ума будет)

    Reply
  3. PiccaHut001

    «15. Размещение восьми ферзей на шахматной доске для СУБД Oracle» и 1С неразрывно связаны. Я вот, каждый день прихожу на работу, попью чаю, и сразу думаю, как-бы разместить 8(ВОСЕМЬ!!!) ферзей на шахматной доске. Ситуация очень жизненная, у каждого дома должно быть 4 набора шахмат, чтобы получилось восемь ферсей, а то некомильфо. Спасибо автору, не поленился, и собрал вместе такие нужные ссылки.

    Reply
  4. tindir

    забавно, что если 1с писать на басурманском, то он легким движениме руки начинета походить на JS со сторонними библиотеками=)

    Reply
  5. ildarovich

    (4) PiccaHut001, здесь задачу 15 и ее решение я привел по нескольким причинам:

    — возможно, кто-то захочет ее решить на «1С» и можно будет сравнить длину решения;

    — возможно, кому-либо будет интересно как выглядит язык запросов СУБД Oracle;

    — возможно, кому-либо будут интересны новые возможности языка запросов Oracle, примененные в этом решении, так как эти возможности могут когда-либо появиться и в 1С, в том числе, и нашими стараниями.

    А вообще это известная классическая задача, которую можно решить для тренировки или просто для удовольствия, если нравится программировать.

    Reply
  6. adhocprog

    пп.11,13 — жесть )

    Reply
  7. alexey_kurdyukov

    (5) tindir, Чем? Тем, что в нём тоже есть слова?

    вот 1С:

    function W(k,a=0,b=0)return?(k<1,»»,W(k-1,a+b)+a%2+W(k-1,a+1+b,1))endfunction

    вот JS:

    function W(k,a,b) {return (k<1?»»:W(k-1,a+b)+a%2+W(k-1,a+1+b,1))}

    вот Pascal:

    function W(k: real,a: real,b: real) begin if (k<1) then result:=»»; else result:=W(k-1,a+b)+a%2+W(k-1,a+1+b,1)); end; end

    вот VB:

    function W(k,a,b) if (k<1) then W:=»» else W:=W(k-1,a+b)+a%2+W(k-1,a+1+b,1)) end if end function

    может на VB больше похоже? или может все языки одинаковые?

    Reply
  8. amon_ra

    Достаточно интересная подборка и описано все занимательно, однако, названия переменных состоящих из одной буквы или какого-то странного слога ломает глаза и заставляет напрягать мозг(

    Я наверно из тех, кто уж лучше переменную назовет по длиннее зато ясненько-понятненько.)

    Reply
  9. fjay69
    function W(k,a=0)return?(k,»»,W(k-1,0)+a+W(k-1,1))endfunction

    Что я делаю не так?

    Reply
  10. awa

    Задача 11.

    Итого 75 символов. Можно ли короче?

    Можно.

    функция г(ё,н=»0″)return?(ё,г(ё-1)+н+г(ё-1,1),»»)endfunction

    Итого 60 символов.

    Reply
  11. fjay69

    (11) awa, про аргумент по умолчанию я и забыл)

    Reply
  12. awa

    (10) У нас одинаковые решения! Объединяя их, получаем 58 символов.

    функция г(ё,н=0)return?(ё,г(ё-1)+н+г(ё-1,1),»»)endfunction
    Reply
  13. ildarovich

    (9) amon_ra, я первое время спорил, потому что сохранились привычки программирования и чтения программ на других языках, а теперь просто соглашусь. И буду стараться использовать в других подходящих случаях содержательные названия переменных. Раз уж так все здесь привыкли (со своим уставом в чужой монастырь не ходят).

    И еще тут был интерес сделать код не скучно-понятным, а смешным (ёж, уж, що, ох, ах, ух) и нарядным. Но не все это правильно понимают — слишком серьезные тут многие, что-ли.

    Reply
  14. ildarovich

    (13) awa, — супер! Мне тогда показалось, что без третьего параметра никак не обойтись, хотя ощущение его ненужности было. Вывод: нельзя было останавливаться на достигнутом!

    Reply
  15. Yashazz

    Кое-что уже можно сделать иначе, благо возможности платформы растут, но…

    Спасибо за полузабытое удовольствие читать красивый код, спасибо за «вкусные» и изящные решения. Эстетично.Стильно. Прям даже не 1С, а настоящее программирование.

    Респект ишшо раз!

    p.s. и да, это случай, когда (14) более уместны именно одно-двух-буквенные переменные, опять же ностальгия…

    Reply
  16. karpik666

    Долго пытался вникнуть в рекурсию в решении задачи 11. И пока думал пришел к другому решению:

    По сути при каждом складывании листа изгиб никуда не девается, он так и будет занимать свой 0 или 1 в последовательности, просто каждый раз добавляем слева и справа для каждого изгиба в последовательности 0 и 1, например: был 0, при следующем изгибе добавляем 0 и 1 получаем 001, затем еще раз сгибаем: 0010011. Поэтому при решении такой задачи использовал Массив и функцию вставить, чтобы он динамически раздвигался. Может мое решение не такое изящное, но мне кажется более понятное.

    Наконец-то разобрался=) идея получается точно такая же, просто у меня реализация ужасная.

    Reply
  17. karpik666

    И еще хотел спросить по решению:

    function W(k,a=0,b=0)return?(k,W(k-1,a+b)+a%2+W(k-1,a+b+1,1),»»)endfunction

    Разве 1С такое может, чтобы переменная, если равна нулю, то одновременно передавала и значение Ложь, а если не равно, то Истина?

    Reply
  18. zqzq

    (14) Понятные и адекватные названия переменных и нормальное оформление кода — это не изобретение 1С, а общемировая практика хорошего программирования. См. классическую книгу С. Макконел «Совершенный код» (S. MacConnel «Code Complete»). Кстати, по поводу «ужей» и «ежей» там тоже было:

    Не используйте имена, которые совершенно не связаны с тем, что представляют переменные Использование имен вроде margaret и pookie практиески гарантирует, что никто другой их не поймет. Не называйте переменные в честь девушки, жены, любимого сорта пива и т. д., если только девушка, жена или сорт пива не являются представляемыми в программе «сущностями». Но даже тогда

    вы должны понимать, что все в мире изменяется, поэтому имена девушка, жена и любимыйСортПива гораздо лучше!
    Reply
  19. ildarovich

    (19) zqzq, есть у меня эта книга, читал ее.

    Но для меня в задаче 3 уж и еж — являются представляемыми в программе сущностями. Они как бы идут (ползут) по массиву в процессе его обработки. При этом их положение взаимосвязано — как и в природе, если они встречаются. В этом и был интерес в этих названиях. Ну и «що» — это просторечное «что», которое отмечает результат сравнения — что случилось и куда двигаться ежу.

    Знаете, есть даже конкурсы, в которых программы пишутся так, чтобы получались стихи. У нас программы на русском языке и мы можем придать за счет этого им больше выразительности.

    Это упражнение, этюд, я не призываю так оформлять все свои программы.

    Но польза от таких упражнений есть.

    Например, в работе http://infostart.ru/public/294285/ я постарался, не теряя смысла, назвать все переменные короткими четырехбуквенными словами, отражающими еще смысл данных переменных. Порадовался богатству языка: у нас очень много коротких выразительных слов: тень, ранг, след, рост, путь, плюс. Там только «змея» оказалось не на месте, хотя и отражала зигзагообразный порядок обхода массива. Но, посмотрев на результаты со стороны, послушав критику людей, которым это представление динамики выполнения программы оказывается недостаточно близким (у них могут быть свои ассоциации), решил больше так не делать и использовать все же в дальнейшем более понятные словосочетания в качестве имен переменных.

    Ну и потом, объясните мне, почему в математических формулах используются короткие названия сущностей. Ведь формулы должны быть еще более понятны: они исключительно для чтения читателями.

    Reply
  20. amon_ra

    (14) Как раз юмор понятен, но если один пример, то читается легко, но после 3-4 уже сложнова-то прочитывать код.

    Reply
  21. amon_ra

    (20) А вы оказывается не плохой философ! ) Вы уж не обижайтесь на наши придирки — мы просто еще не постигли дзен программирования) Теперь на ваши куски кода смотрю иным взглядом)

    Reply
  22. pm74

    на форуме была задача по смыслу почти обратная № 2 :

    По строке вида «1,2,3,5,9-15» найти количество цифр в последовательности.

    Вот решение в духе минимализма:

    Строка=»1,2,3,5,9-15″;
    Число=0;
    Выполнить(«Строка=»»Вычислить(«»+Вычислить(«»»+СтрЗаменить(Строка,»,»,»»»)*-1+»»)+Вычислить(«»+Вычислить(«»»)+»»»)*-1+»»)»»»);
    Выполнить(«Число=Вычислить(«+СтрЗаменить(СтрЗаменить(Строка,»-«,»0*»),»(«,»(1+»)+»)»);
    Сообщить(«Результат =»+Число);
    Reply
  23. ildarovich

    (23) pm74, ага, видел краем глаза уже с решением. Оригинальная идея. Тогда не нашел возможности улучшить. Но вообще бы подумал как бы это записать покрасивее и обобщить.

    Reply
  24. egorovntn

    Да не которые примеры интересны, давно думал как это реализовать еще с олимпиад известные задачи, а руки то не доходили…

    Reply
  25. Патриот

    сразу в глаза бросилась ненужность параметра Б. Хотел своё сокращение привести

    function W(k,a=0,b=0)return?(k,W(k-1,a+b)+b+W(k-1,a+b+1,1),»»)endfunction

    залез в комменты почитать и понял, что я на несколько дней опоздал, и уже найдены решения где от него полностью избавились =((

    Reply
  26. DrAku1a

    Заметочки про 1С:Предприятие # Про быстрые массивы — вот это действительно ВЕЩЬ! и как раз в стиле минимализма…

    Reply
  27. DrAku1a

    (8) alexnecro, да это как языки общения — в принципе, используются для одной общей цели (общаться с железом) — просто немного разная специфика у каждого языка. Простейшие задачи с примитивными расчетами — можно решать практически в любом языке высокого уровня (а может и не только высокого). Выбор языка — вопрос удобства, надёжности и простоты общения на нём…

    Например, оперируя в Delphi — мне не хватает удобных коллекций данных, реализованных в 1С (список, таблица значений, структура, соответствие), универсальности типов значений, беззаботного отношения к создаваемым объектам. Всё это можно реализовать, конечно — через компоненты. Интерфейс и функционал стандартных компонентов — тоже уступает 1С и тоже навёрстывается компонентами… Зато в Delphi я могу написать программу, не связанную с базой данных, выполняющую вообще — другие функции…

    Reply
  28. Патриот

    (26) Решил ещё раз штурмануть задачу 11, но уже с целью выведения формулы определения i-того символа в нужной последовательности (причём количество сгибаний нас не интересует, т.к. последовательность n-того порядка является началом любой другой последовательности более старшего порядка, значит можно исходить из того, что мы имеем независимую (от n, например) бесконечную последовательность). Возможно продолбался бы я не один день с этой идеей, если бы вовремя не заметил, что наша последовательность, это запись самодвойственной функции! С которыми я по первому курсу универа пропарился немало, т.к. преподаватель дискретной математики очень заинтересовал нерешёнными досель вопросами в этой области. Подробностей не помню, но смысл в том, что пока такой формулы нет и не предвидится (что её нельзя вывести, тоже вроде не доказано), так что я смело отказался от данной затеи.

    Но вдруг кого заинтересует более решаемая задача — Написать суперкороткую функцию, которой на вход мы скармливаем номер символа последовательности, рождаемой в задаче 11, а на выходе выплёвывается искомый символ. В принципе сиё достигается небольшой модификацией исходного решения. На досуге накидаю.

    Reply
  29. Sardukar

    (20)

    «Ну и потом, объясните мне, почему в математических формулах используются короткие названия сущностей. Ведь формулы должны быть еще более понятны: они исключительно для чтения читателями. «

    Чтобы математики другим казались умнее.

    Reply
  30. bashirov.rs

    Не плохо написано! Спасибо за собранный материал. Ждем еще…

    Reply
  31. DAnry

    Спасибо! Хорошая подборка. Интересные оригинальные решения, так сказать гимнастика для мозга. Но есть и полезные, которые можно использовать в работе.

    Reply
  32. KeyFire

    Спасибо. Познавательно.

    Reply
  33. ildarovich

    Добавил задачу 16 про недостающие функции для работы с датами (как в языке запросов).

    На самом деле довольно интересно то, что

    ДобавитьКДате(‘20120131’, 1, «Месяц») = ‘20120229’,
    ДобавитьКДате(‘20120131’, 3, «Месяц») = ‘20120430’,
    ДобавитьКДате(‘20120130’, 3, «Месяц») = ‘20120430’
    ДобавитьКДате(‘20120229’, 1, «Год») = ‘20130228’

    Также не все обращают внимание, что

    РазностьДат(‘20131231235959′,’20140101000000’,»Год») = 1 и
    РазностьДат(‘20131231235959′,’20140101000000’,»Час») = 1

    Как в шутке про прошлогодние салаты на Новый год

    Также интересно, что инициализация структуры Шаг

    может проводиться таким образом

    Шаг = Новый Структура(«Месяц, Секунда», 1, -1);
    Шаг.Добавить(«Минута», Шаг.Секунда * 60);
    Шаг.Добавить(«Час», Шаг.Минута * 60);
    Шаг.Добавить(«День», Шаг.Час * 24);
    Шаг.Добавить(«Неделя», Шаг.День * 7);
    
    Шаг.Добавить(«Квартал», Шаг.Месяц * 3);
    Шаг.Добавить(«Год», Шаг.Квартал * 4);

    Это упростит поддержку 1С в поселении на Марсе 🙂

    Reply
  34. AlexanderKai

    (18) karpik666,

    Может. Так по умолчанию принято.

    Reply
  35. ZLENKO

    Возможно я ошибаюсь, но в алгоритме «7. Связывание таблиц значений по ФИФО» часть записей одной из таблиц, которые не «связались» не попадут в результирующую таблицу ?

    Когда будет обработана последняя запись «меньшей» из таблиц, то цикл прервется по условию «Пока ё < А.Количество() И ж < Б.Количество() Цикл», т.к. условие «И».

    Просто заменить на «ИЛИ» тоже нельзя — неправильно будет работать 🙁

    Просто я помню возился с такой задачкой и «красивого» алгоритма не получилось 🙁

    Изначально написал почти такой же алгоритм, но «не взлетело»…

    Пришлось добавлять «обработку хвостов» и вся «красивость» исчезла.

    Reply
  36. ZLENKO

    (34) «ДобавитьКДате(‘20120229’, 1, «Год») = ‘20130228’»

    А еще вариант: ДобавитьКДате(‘20110228’,ГОД, 1) = ‘20120228’, а не ‘20120229’ 🙂

    Reply
  37. ildarovich

    (36) ZLENKO.PRO, нет, не ошибаетесь, я должен был добавить в описание, что предварительно добиваемся, чтобы А.Итог(«Сумма») = Б.Итог(«Сумма») за счет ПРЕДВАРИТЕЛЬНОГО дописывания последней записи к таблице с меньшей суммой. В коде, откуда это было выдернуто, это делалось в другом модуле.

    (37) Так вроде бы тоже самое и написано. — Ровно тот же пример.

    Про 20120228 + Год, наверное, стоит добавить.

    Reply
  38. miniogn

    16. Добавить к дате и разность дат

    В данном случае получается красиво. Но в ущерб скорости. Создание структур вовсе не обязательно делать для такой задачи.

    Reply
  39. ildarovich

    (39) miniogn, в комментариях к статье, где обсуждалась задача было сказано (ссылка приведена), что создание структуры Шаг можно вынести из тела функции для повышения производительности. Можно сделать ее глобальной и создавать ее один раз в соответствующем модуле. Это решит все проблемы с производительностью.

    Наверное, эту мысль нужно было перенести и сюда.

    Но вот еще что действительно интересно.

    Если этот прием понимать как реализацию сложного селекта, с большим количеством ИначеЕсли, в котором проверяются строки или числа, то не будет ли это просто быстрее? Сколько «стоит» создание структуры? — Можно еще исследовать этот вопрос. Для данной задачи я делал замеры — получается медленнее, но не намного. Числа есть в упомянутых комментариях.

    Reply
  40. ildarovich

    Добавил минимализм 17.

    Приведен набор из трех коротких функций. С его помощью можно получать готовый массив любого заданного размера N, содержащий последовательность чисел от 0 до N — 1. Этот массив затем, например, можно загрузить в нужную колонку таблицы значений, чтобы перенумеровать ее строки, не используя цикл. Такой способ в 3 раза МЕДЛЕННЕЕ нумерации таблицы значений в цикле. Поэтому для практических целей он не подойдет — только как основа для какого-либо другого решения.

    Используется «Порождающий запрос» (с), текст которого генерируется для заданного числа N очень короткой рекурсивной функцией prototext.

    Reply
  41. miniogn

    (40) >Можно сделать ее глобальной и создавать ее один раз в соответствующем модуле. Это решит все проблемы с производительностью.

    На сервере будете создавать? А как же клиент… Или будет вызов сервера.

    Или каждый раз перед вызовом создавать локально и заполнять? Тоже мало смысла.

    В общем еще хуже будет. В исходном варианте хотя бы рабочий вариант.

    Reply
  42. ildarovich

    (42) miniogn, затраты времени на создание этой структуры не значительны.

    Я говорил про вынос определения этой структуры из тела функции, если вдруг время ее выполнения будет критично. Куда помещать определение структуры Шаг — зависит от задачи. По моему мнению на клиенте массовых вычислений с использованием этих функций быть не должно. Скорее всего, это будет какой-либо алгоритм, выполняемый на сервере.

    Reply
  43. ildarovich

    Добавил задачу 18.

    «Простой трюк для быстрого объединения таблиц значений».

    Первоначально эта задача была опубликована как отдельная статья, которую набрала довольно большой рейтинг.

    К сожалению, из-за досадной ошибки в замерах эффект предложенного метода в статье был сильно завышен. В статье говорилось об ускорении в 10 и более раз. Тогда как на самом деле максимальное ускорение — всего в полтора раза. Поэтому статья, получившая незаслуженные оценки, была снята с публикации, а ее начинка помещена сюда под номером 18.

    Reply
  44. mylogin
    Все возможности оптимизация данного способа ограничиваются записью в одну строку и выбором таблицы с меньшим количеством элементов в качестве источника добавляемых строк.

    Я всегда думал, что выигрыш в производительности от уменьшения количества строк кода возникает только при отладке.

    Reply
  45. ildarovich

    (45) mylogin, некоторый выигрыш все-таки есть. Посмотрите в статье Заметочки про 1С:Предприятие 8

    Reply
  46. mylogin

    (46) Да, действительно. Спасибо, будем знать.

    Reply
  47. gigagr

    Спасибо за собранный материал.

    Reply
  48. aspirator23

    (44) Спасибо.Из кода 5% выжимают, а тут 50. Подарок.

    Reply
  49. StaticUnsafe

    (6) решал задачу с ферзями на 1С, удивлял препода в инсте )))

    Reply
  50. ksuman
    Reply
  51. ildarovich

    (51) ksuman, спасибо за такой подробный комментарий.

    Не буду спорить, я много раз слышал эти доводы и сам много раз говорил те же слова другим.

    Но когда ищешь короткое решение и находишь «легальную» возможность его сокращения, то психологически трудно вовремя затормозить, не убрав еще одну строчку, обратившись к реквизиту через десять точек и тому подобное.

    Те решения, от которых я отталкивался были в пять и больше раз длиннее. Совершенно ненужная избыточность в них точно была. И минимизация заключалась не только в сокращении имен переменных и записи в одну строчку. Где-то я переборщил. Я это уже понял. Здесь больше чем в других программистких сообществах ценят не компактность кода, а простоту и наглядность кода. Буду иметь это ввиду, наступая на горло своим привычкам.

    Ну и, кстати, в начале статье открытым текстом написано, что приведены сублиматы кода и перед использованием их следует размачивать.

    возможно, кто-то захочет ее решить на «1С» и можно будет сравнить длину решения

    это относилось к обоснованию того, зачем нам здесь код на Oracle. В исходной статье можете посмотреть каким был исходный код. Видно, что имена переменных и форматирование кода там были очень краткими и совсем «не в стиле 1С». Полюбопытствуйте, как пишут ораклисты. Я написал код в их стиле и гораздо короче и гибче, применив рекурсию. Попробуйте предложить несокращаемое компактно-понятно-наглядное решение на 1С для этой задачи.

    Про то, что явное объявление локальных переменных экономит время раньше не знал.

    Reply
  52. ildarovich

    Добавил задачу 19 «загадка суммы и произведения». Приведено короткое решение этой переборной по сути задачи. Использован один пакетный запрос и техника искусственных таблиц. О задаче узнал от scientes. Запросы в пакете отражают последовательность ограничений, накладываемых на числа Х и У.

    Reply
  53. zqzq

    За остатки на каждый день спасибо, полезный запрос. Можно туда же добавить и начальный остаток из вашего комментария к той статье (проверил — вроде правильно считает).

    Reply
  54. ildarovich

    Добавил задачу 20 «Расчет поразрядного исключающего ИЛИ». Сам запрос понадобился для решения головоломки про 64 монеты http://habrahabr.ru/post/250585/. Но вообще его можно использовать для подсчета контрольных сумм по исключающему ИЛИ, инвертирования двоичных разрядов в числах и прочих поразрядных битовых операциях.

    Reply
  55. ildarovich

    Добавил задачу 21 «Как с помощью запроса посчитать количество символов в реквизите?» Большую часть кода там занимается часть, формирующая таблицу чисел 1-64.

    Reply
  56. mailrum2004

    Интересно, спасибо! Запрос из «19. Загадка суммы и произведения» не заработал сразу.

    дописал в первой строке «КАК Х»

    ВЫБРАТЬ 0 КАК Х
    Reply
  57. ildarovich

    (57) mailrum2004, спасибо за замечание: была опечатка, сейчас поправлю.

    Reply
  58. vasyak319

    Функции Квартал не хватает «+1» перед «;»

    Reply
  59. ildarovich

    (59) vasyak319, спасибо, поправил

    Reply
  60. Rusmus

    задачу 21 (Определение длины строки в запросе) у себя делаю по такому принципу:

    ВЫБРАТЬ

    Дано.*,

    ЕСТЬNULL(ё, «256+») КАК Длина

    ИЗ

    Дано

    ЛЕВОЕ СОЕДИНЕНИЕ Р543210

    ПО ПОДСТРОКА(Дано.Строка,ё,1) <> «» И ПОДСТРОКА(Дано.Строка,ё+1,1) = «»

    Преимущества:

    не портится таблица Дано — записи с длинными строками не пропадут, одинаковые записи не сгруппируются

    полей в Дано может быть сколько угодно; не надо писать список в разделе «сгруппировать по»

    Как думаете, какая будет разница по скорости?

    Reply
  61. ildarovich

    (61) Rusmus, отличная идея! — Возьму на вооружение. — Согласен насчет преимуществ. Одно уточнение: нужно писать

    ПО ПОДСТРОКА(Дано.Строка,ё,1)  + «!» <> «!» И ПОДСТРОКА(Дано.Строка,ё+1,1) + «!»= «!» 

    чтобы Длина строки «мама мыла раму» не считалась равной одновременно 4, 9 и 13.

    По скорости, думаю, выигрыша не будет. За счет двойного вычисления подстроки может быть даже проигрыш в простых случаях. Но преимущества перевешивают.

    Reply
  62. Rusmus

    (62) спасибо за дополнение.

    Reply
  63. ya.Avoronov

    Я тут один такой?

    — Прочитал статью — лайкнул статью;

    — Прочитал комментарии — лайкнул пару комментариев;

    — Лайкнул бы и автора);

    — Не нашел применения сему в своей жизни — забыл все как в страшном сне.

    Ощущение, как во время олимпиады по информатике в 9 классе.

    Reply
  64. herfis

    Очень соблазнительный вариант простого алгоритма «Остатки на каждый день». Автор также везде советует его в комментариях к другим публикациям. Заявляется, что его производительность лучше стандартного «тяжелого» варианта. Но ведь это только для отчета с фиксированными группировками. Подавляющее большинство реальных отчетов базируются на СКД и имеют настраиваемые группировки. А значит — не получится в запросе выполнить свертку. А в этом случае на вход СКД приползет в разы большее количество детальных записей, чем в «тяжелом» варианте. Тесты не проводил, но вполне может оказаться, что на отчетах обрабатывающих большое количество данных такая оптимизация может выйти боком.

    Reply
  65. ildarovich

    (65) herfis, трудно возражать на неконкретные замечания типа «если кто-то кое-где у нас порой», или

    Тесты не проводил, но вполне может оказаться

    Во-первых, приведите (в виде текста запроса) тот вариант, который вы считаете лучшим. Насколько я понимаю, всего есть два разных популярных принципа восстановления остатков на дни без оборотов. В первом суммируются обороты. Во втором остатки на дни с оборотами интерполируются по принципу срезов последних. Я за первый вариант и против второго, который кажется мне объединением недостатков разных техник.

    Но и в первом и втором группировки для получения остатков фиксируются. Ну а как иначе? Здесь я ничего принципиально не менял (как в «Баттерфляй», например), просто записал известный прием короче (в одном запросе). Поэтому данное замечание кажется странным.

    Reply
  66. herfis

    (66) Вы правы. Заработался. В голове все смешалось 🙂 Приношу извинения. Вылетело из головы, что в «тяжелом» варианте тоже фиксированные группировки. Сейчас как раз делаю новый отчет с использованием этого подхода. В комментариях к статье http://infostart.ru/public/102435 приложил рабочую формулу для начального остатка.

    Reply
  67. ildarovich

    Следующая серия минимализмов опубликована в продолжении этой статьи, которая называется «Минимализмы 2».

    Reply
  68. Ovrfox

    К задаче 20. Поразрядное исключающее ИЛИ

    Насколько я понял в последнем запросе ошибка

    Должно быть примерно так:

    ВЫБРАТЬ

    Разряды.Вес * (СУММА (Разряды.Икс) — ВЫРАЗИТЬ(СУММА(Разряды.Икс) / 2 + 0.5 КАК ЧИСЛО(10, 0)) * 2 + 2) КАК Икс

    ИЗ

    (ВЫБРАТЬ

    Позиции.Вес КАК Вес,

    СУММА((ВЫРАЗИТЬ(Дано.Икс / Позиции.Вес + 0.5 КАК ЧИСЛО(10, 0))) — 1) КАК Икс

    ИЗ

    Дано КАК Дано,

    Позиции КАК Позиции

    СГРУППИРОВАТЬ ПО

    Позиции.Вес) КАК Разряды

    Reply
  69. ildarovich

    (69) Ovrfox, нет, там ВСЕ ПРАВИЛЬНО. Запрос в результате получает ОДНО число. Это контрольная сумма, полученная поразрядным ксором шести разрядов чисел в таблице Дано.

    Запрос довольно хитрый. Хитрость в том, младшие биты заранее (на промежуточных этапах) выделять не нужно. Их можно выделить уже после суммирования, что и сделано. То есть младший бит суммы (XOR) равен сумме (XOR) младших битов.

    Я проверял запрос в консоли. Можете тоже проверить сами.

    Reply
  70. Ovrfox

    (70) Верно, Без вложенного запроса не обойтись.

    Сначала вычисляем четность по разрядно, а потом приводим ее к числу.

    Но если кому то нужна четность по разрядно, то ее можно получить и одним запросом.

                    ВЫБРАТЬ
    СУММА(Разряды.Вес * Разряды.Икс) КАК Икс
    ИЗ
    (ВЫБРАТЬ
    Позиции.Вес КАК Вес,
    СУММА((ВЫРАЗИТЬ(Дано.Икс / Позиции.Вес + 0.5 КАК ЧИСЛО(10, 0))) — 1) — (ВЫРАЗИТЬ(СУММА((ВЫРАЗИТЬ(Дано.Икс / Позиции.Вес + 0.5 КАК ЧИСЛО(10, 0))) — 1) / 2 + 0.5 КАК ЧИСЛО(10, 0))) * 2 + 2 КАК Икс
    ИЗ
    Дано КАК Дано,
    Позиции КАК Позиции
    
    СГРУППИРОВАТЬ ПО
    Позиции.Вес) КАК Разряды

    Показать

    PS: Как хреново, что обычных мат операций (как целочисленное деление) нет в языке запросов 1С!

    Reply
  71. ildarovich

    (71) Ovrfox, это метод «в лоб». В нем вычислений

    — (ВЫРАЗИТЬ(Разряды.Икс / 2 + 0.5 КАК ЧИСЛО(10, 0))) * 2 + 2

    гораздо больше. Во столько раз, сколько чисел в таблице Дано. А в моем варианте для сокращения объема вычислений используется интересная математическая закономерность. То есть все не просто так.

    По поводу отсутствия некоторых функций в языке запросов тоже сожалею. Громоздкость некоторых конструкций сильно раздражает. Есть, правда, некоторые мысли по этому поводу (что можно сделать). Может, дойдут руки.

    Reply
  72. Ovrfox

    (72)Насколько я знаю MS SQL, то значение (ВЫРАЗИТЬ(Дано.Икс / Позиции.Вес + 0.5 КАК ЧИСЛО(10, 0)) — 1) скорее всего будет вычислено для каждого элемента (декартового произведения таблиц запроса) один раз, а не два.

    Операция же с суммами будет выполнена один раз для каждого значения группировки. Это очевидно.

    Это означает, что в упомянутом запросе вычислений ровно столько же, сколько и в Вашем варианте. Ни на одно больше.

    Reply
  73. EmpireSer
    Reply
  74. kuzyara
    Reply
  75. denis_aka_wolf

    (29) Ругается что поля А и Б не входят в группу

    Весь мой запрос:

    ВЫБРАТЬ «Овсянка» А, «Омлет» Б
    ПОМЕСТИТЬ Дано
    ОБЪЕДИНИТЬ
    ВЫБРАТЬ «Плов»,»Борщ»
    ОБЪЕДИНИТЬ
    ВЫБРАТЬ «Омлет»,»Овсянка»
    ОБЪЕДИНИТЬ
    ВЫБРАТЬ «Пельмени»,»Шашлык»
    ОБЪЕДИНИТЬ
    ВЫБРАТЬ «Борщ»,»Плов»
    ;
    
    ВЫБРАТЬ А, Б, КОЛИЧЕСТВО(*)
    ИЗ (ВЫБРАТЬ А, Б ИЗ Дано ГДЕ А <= Б
    ОБЪЕДИНИТЬ ВСЕ
    ВЫБРАТЬ Б, А ИЗ Дано ГДЕ А > Б) ВЗ

    Показать

    Reply
  76. denis_aka_wolf

    (76) ошибочка вышла, не туда написал, извините…

    Reply
  77. EmpireSer

    (75)

    Я заметил, что ты дополнительно защитился от того, когда в Ч параметры y или М или d могут быть нулями. Я как раз напоролся на это у себя.

    Но вот кое чего мы забыли: формат даты может быть и на русском языке! Например «ДФ=ггггММ»

    (1С может переваривать так же и формат, когда русские буквы перемешаны с английскими)

    И как это обработать?

    Reply
  78. pm74

    было или нет не знаю , может быть пригодится

    Функция МассивСтрокВСтроку(Массив)
    Если Массив.Количество()>0 Тогда
    Возврат ЗначениеИзСтрокиВнутр(СтрПолучитьСтроку(Стрзаменить(ЗначениеВСтрокуВнутр(Массив),»»»},»+Символы.ПС+»{«»S»»,»»»,»»),3));
    Иначе
    Возврат «»;
    КонецЕсли;
    КонецФункции
    

    Показать

    Reply
  79. bulpi

    По поводу задачи № 6 — остатки на каждый день. Автор пишет «Правда, здесь рассчитываются остатки на конец каждого дня (это легко поправить, сдвинув даты на -1).» Да, но СКД не захотела у меня сдвигать на 1 день почему-то (возможно, из-за моего неумения). Поэтому могу предложить текст запроса для получения НАЧАЛЬНЫХ остатков на каждый день без сдвига дат :

    ВЫБРАТЬ
    Движения.Номенклатура,
    ДНИ.Период КАК ДатаОстатка,
    СУММА(ВЫБОР
    КОГДА Движения.Период = &НачалоПериода И Движения.Период =ДНИ.Период  ТОГДА Движения.КоличествоНачальныйОстаток
    КОГДА Движения.Период = &НачалоПериода И Движения.Период <ДНИ.Период  ТОГДА Движения.КоличествоКонечныйОстаток
    КОГДА Движения.Период < ДНИ.Период   ТОГДА Движения.КоличествоОборот
    ИНАЧЕ 0  КОНЕЦ
    ) КАК НачальныйОстатокНаДату
    ИЗ
    Дни КАК ДНИ,
    РегистрНакопления.ЗапасыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, День) КАК Движения
    
    СГРУППИРОВАТЬ ПО
    Движения.Номенклатура,
    ДНИ.Период
    

    Показать

    Reply
  80. bulpi

    (80)

    Хм… а как раскрасит по синтаксису запроса, а не кода?

    Reply
  81. binex

    (80)

    Таким запросом вы Начальный остаток только на одну дату получите — на &НачалоПериода

    ПС. Хотя ещё не до конца разобрался. Но что-то тут не так. )

    Reply
  82. qazaz2

    Огромное спасибо Автору, уйму времени сэкономил.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *