Задать вопрос
  • Как выполнить ssh запрос в laravel?

    erge
    @erge
    Примус починяю
    Попробуйте
    ssh-client - defstudio/ssh-client
    ssh-tunnel - prodigyphp/laravel-ssh-tunnel

    ps: альтернатива php ssh2_connect, можно свой враппер написать.
    updated
    Ответ написан
    Комментировать
  • Конвертировать px в rem с помощью bash скрипта?

    erge
    @erge
    Примус починяю
    зачем это делать на bash с включением grep, sed и awk, когда все можно сделать на одном awk:

    awk -F: '
    /\{|\}|border|max-width|^$/ { print $0 }
    !/\{|\}|border|max-width|^$/ {
      split( substr($2, 1, length($2)-1) , a," ");
      res = "";
      for (i in a) {
        ind = match(a[i], /[0-9]+px/)
        if (ind != 0) {
          a[i] = sprintf ("%.2frem", a[i]/10);
        }
        res=a[i] " " res;
      }
      res = substr(res, 1, length(res)-1);
      print $1 ": " res ";"
    }
    ' some.css


    см. пример на awk.js.org

    UPDATE:
    заметил что значения перемешиваются (могут перемешиваться когда их 4 и более), это происходит ввиду того что массивы в awk ассоциативные и поэтому при переборе через for in они могут случайно перемешаться.
    Arrays in awk are different—they are associative. This means that each array is a collection of pairs—an index and its corresponding array element value...
    The pairs are shown in jumbled order because their order is irrelevant.

    см. 8.1.1 Introduction to Arrays

    переписал на перебор индексов и немного "оптимизировал", убрал форматирование %.2f т.к. при делении на 10 оно не нужно...
    awk -F: '{
    if ($0 ~ /\{|\}|border|max-width|^$/ ) { print $0 }
    else {
      res = "";
      split( substr($2, 1, length($2)-1) , a, " ");
      for (i=1; i<= length(a);i++) res = res " " ((match(a[i], /[0-9]+px/) != 0)? a[i]/10"rem" : a[i]);
      print $1 ": " res";"
    }
    }' some.css
    Ответ написан
    2 комментария
  • Как удалить метку (tag) полностью?

    erge
    @erge Автор вопроса
    Примус починяю
    удалил непосредственно в файле .git/info/refs эти строки, сделал коммит, пока полет нормальный...
    Ответ написан
    3 комментария
  • Как посчитать количество подряд идущих одинаковых записей SQL?

    erge
    @erge
    Примус починяю
    Пытался сделать через ROW_NUMBERS() OVER (PATRITION BY date ORDER BY date, time, check), ну тут, конечно, получается он игнорит check и просто проставляет 1,2,3,4,5.


    вы же написали ниже что группировка по дате и чеку, а делаете PATRITION BY date

    Если добавить PATRITION BY date, check, то он, блин, сортирует по check потом и тоже не то выходит


    правильно, потому что необходимо группировать по тем критериям по которым необходимо и делать сортировку по негруппируемому полю по которому надо сделать счет - time

    ROW_NUMBERS() OVER (PATRITION BY date, check ORDER BY time)

    тогда он посчитает как надо.
    а уж если необходимо еще как-то отсортировать или отобрать, то заворачиваете этот запрос в подзапрос или CTE и делаете из него запрос с WHERE , ORDER и т.п. и т.д.
    Ответ написан
    Комментировать
  • Как написать регулярное выражение?

    erge
    @erge
    Примус починяю
    какой ЯП?
    можно находить блоки <a>...</a>
    а уже внутри них искать блоки <b>...</b>

    одной регуляркой, это......... м...

    одной регуляркой даже скорее невозможно, только если знать точное количество блоков <b>...</b>
    или точнее... хотя бы максимальное их количество...

    например максимум их может быть 4, тогда можно написать регулярку вида:
    (?<=<a>)(\s*?<b>([^<]+)<\/b>)(\s*?<b>([^<]+)<\/b>)?(\s*?<b>([^<]+)<\/b>)?(\s*?<b>([^<]+)<\/b>)?


    матчим и в каждом "матче" (совпадении) - если существует группа с нечетным номером, то в следующей группе с четным номером будет собственно значение, т.е. нам нужны только четные группы.

    см, regex101

    PS:
    можно было бы и так... (?<=<a>)(\s*?<b>([^<]+)<\/b>){1,}
    матчиться оно будет, НО, вот группа будет только одна и писаться в нее будет последнее найденное значение.

    как-то так....

    UPDATE
    взяв сгенерированный код в python с regex101, допиливаем "решение в лоб"

    regex = r"(?<=<a>)(\s*?<b>([^<]+)<\/b>)(\s*?<b>([^<]+)<\/b>)?(\s*?<b>([^<]+)<\/b>)?(\s*?<b>([^<]+)<\/b>)?"
    
    test_str = '''
    <a>
    <b>test11</b>
    </a>
    
    <a>
    <b>test21</b>
    <b>test22</b>
    </a>
    
    <a>
    <b>test31</b>
    <b>test32</b>
    <b>test33</b>
    </a>
    
    <a>
    <b>test41</b>
    <b>test42</b>
    <b>test43</b>
    <b>test44</b>
    </a>
    
    <c>
    <b>test51</b>
    <b>test52</b>
    </c>
    '''
    
    matches = re.finditer(regex, test_str, re.MULTILINE)
    
    for matchNum, match in enumerate(matches, start=1):
        for groupNum in range(0, len(match.groups())):
            groupNum = groupNum + 1
            if (groupNum % 2 == 0) & (match.group(groupNum) != None):
                print (match.group(groupNum) )


    см. пример
    Ответ написан
    Комментировать
  • Как отобразить различный текст в зависимости от времени добавления данных в БД?

    erge
    @erge
    Примус починяю
    для MySQL смотрите функции работы с датами и CASE WHEN
    DATETIME приводите к DATE и через CASE WHEN определяете

    SELECT
        id,
        dt,
        CASE DATE(dt)
          WHEN CURDATE() THEN 'Сегодня'
          WHEN CURDATE() + INTERVAL -1 DAY THEN 'Вчера'
          ELSE 'Ранее'
        END AS when_day
      FROM items
    ;


    см. пример

    для PHP аналогично, смотрите switch case и DateTime для работы объектом, который представляет дату и / или время и методы для манипуляции с ними.

    $now = new DateTime();  // текущая дата
      switch ($DATEPOSTED) { // в формате Y m d
        case $now->format("Y m d"):
            echo "сегодня";
            break;
        case ((clone $now)->modify("yesterday"))->format('Y m d'):
            echo "вчера";
            break;
        default:
            echo "ранее";
      }


    PS: здесь (clone $now) я клонирую $now, чтобы не изменять основную переменную, если обернуть в функцию то это не обязательно, см. пример ниже.

    см. полный пример

    UPDATE:
    касательно кода в стилистике автора
    $DATEPOSTED = strtotime("-1 day");
    здесь вчерашний день задается неверно!
    во-первых, strtotime - Преобразует текстовое представление даты на английском языке в метку времени Unix
    во-вторых, время Unix (timestamp) не совпадает с форматом заданным выше и в $now - Y m d, поэтому сравнивать их некорректно, необходимо приводить дату к одному формату Y m d
    $DATEPOSTED = date('Y m d', strtotime(' -1 day'));
    далее по условию, если необходимо просто сравнивать с сегодня и что не сегодня то это вчера, то условие вообще банальное:
    if ($now == $DATEPOSTED) {
    Ответ написан
    Комментировать
  • Как настроить кодировку sql developer?

    erge
    @erge
    Примус починяю
    У меня в Oracle SQL Developer так:
    Tools -> Preferences

    Вкладка Envirement: Encoding: UTF-8

    Вкладка Database -> NLS:
    Language: RUSSIAN,
    Territory: RUSSIA,
    Sort: RUSSIAN,
    Date Language: RUSSIAN

    PS: правда девелопер старенький, но не думаю что местоположение настроек сильно отличается.
    Ответ написан
    Комментировать
  • Как загрузить данные в таблицу из csv в postgres с помощью python (psycopg2)?

    erge
    @erge
    Примус починяю
    Если прям вот вообще надо исключительно через скрипт и исключительно через python, то
    читаешь csv файл построчно, собираешь в массив, отправляешь batch insert в постгрис.
    см. executemany(query, vars_list)

    tuples = ((123, "foo"), (42, "bar"), (23, "baz"))
    cur.executemany("INSERT INTO test (num, data) VALUES (%s, %s)", tuples)
    Ответ написан
    Комментировать
  • Как правильно собирать данные с разных таблиц БД?

    erge
    @erge
    Примус починяю
    Для построения такого JSON на SQL вам нужны функции json_agg() / json_build_object(), далее обычные запросы с объединениями и группировкой.

    Пример как собрать JSON author
    SELECT json_build_object(
        'account_id', id,
        'first_name', first_name,
        'last_name', last_name
      ) AS author
      FROM accounts

    post собирается как
    json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )
    при объединении таблиц posts и accounts
    через json_agg собираем в массив
    SELECT json_agg(json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS posts
      FROM posts p
      JOIN accounts a ON a.id = p.author_id

    комментарии аналогично, но с группировкой по постам - post_id
    SELECT json_agg(json_build_object(
        'comment_id', c.id,
        'body', c.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS comments
      FROM comments c
      JOIN accounts a ON a.id = c.author_id
      GROUP BY post_id

    далее объединяем комментарии с постами через post_id = id
    для удобства комментарии вынес в CTE (общее табличное выражение)
    WITH cmts AS (
    SELECT json_agg(json_build_object(
        'comment_id', c.id,
        'body', c.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS comments,
      post_id
      FROM comments c
      JOIN accounts a ON a.id = c.author_id
      GROUP BY post_id
    )
    SELECT json_agg(json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        ),
        'comments', COALESCE(c.comments, '[]')
      )) AS "posts with comments"
      FROM posts p
      JOIN accounts a ON a.id = p.author_id
      LEFT JOIN cmts c ON c.post_id = p.id


    см. пример sqlfiddle
    Ответ написан
    1 комментарий
  • Можно ли написать циклический запрос, получающий последнюю запись из древа, не делая несколько запросов в цикле?

    erge
    @erge
    Примус починяю
    -- вывод ветки дерева
    WITH RECURSIVE
    cte (id, title, parent_id) AS (
      SELECT     id,
                 title,
                 parent_id
      FROM       test
      WHERE      id = 1 -- < id узла от которого выводить
      UNION ALL
      SELECT     t.id,
                 t.title,
                 t.parent_id
      FROM       test t
      INNER JOIN cte
              ON t.parent_id = cte.id
    )
    SELECT * FROM cte;


    для того чтобы идти от потомка к родителю, необходимо "развернуть" связь в ON t.parent_id = cte.id т.е. ON t.id = cte.parent_id и из полученного выбрать запись с parent_id is null

    т.е. так:
    -- вывод самого верхнего родителя по дочернему узлу
    WITH RECURSIVE
    cte (id, title, parent_id) AS (
      SELECT     id,
                 title,
                 parent_id
      FROM       test
      WHERE      id = 4 -- < id узла
      UNION ALL
      SELECT     t.id,
                 t.title,
                 t.parent_id
      FROM       test t
      INNER JOIN cte
              ON t.id = cte.parent_id
    )
    SELECT * FROM cte
      WHERE parent_id IS NULL;


    см. пример

    для MySQL 5+ можно так:

    SELECT * FROM (
      SELECT  id,
              title,
              parent_id 
        FROM (SELECT * FROM test ORDER BY id DESC) test_sorted
        JOIN (select @pv := 4) initialisation -- < id узла
        WHERE find_in_set(id, @pv)
          AND length(@pv := concat(@pv, ',', COALESCE(parent_id, '')))
    ) t
      WHERE parent_id is null
    Ответ написан
    Комментировать
  • Как получить таблицу с верными данными и с исключениями?

    erge
    @erge
    Примус починяю
    Используйте регулярное выражение для отбора числовых значений в population
    population ~ '^[0-9]+$'

    -- Выбираем по population где только число и больше 4000
    SELECT *
      FROM planet_osm_point
      WHERE place = 'town'
        AND population ~ '^[0-9]+$'
        AND population::int > 4000
    
    -- Отбираем нечисловые значение в population и вставляем в таблицу contr_planet_osm_point
    INSERT INTO contr_planet_osm_point
    SELECT *
      FROM planet_osm_point
      WHERE place = 'town'
        AND population !~ '^[0-9]+$'


    см. пример на dbfiddle

    UPDATE:
    по комментариям, для того чтобы "железно" по порядку работало - отбор чисел-> отбор по условию.
    SELECT *
      FROM (
        SELECT *
          FROM planet_osm_point
          WHERE place = 'town'
            AND population ~ '^[0-9]+$'
      ) t
      WHERE population::int > 4000


    UPDATE2:
    да согласен, с xukapy, БД может в принципе как угодно выполнить условия в процессе оптимизации, поэтому лучше жестко задавать порядок выполнения.

    считаю можно как подзапросом выше, так и как пишут в статье - PostgreSQL Antipatterns: вычисление условий в SQL
    использовать CASE -
    WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;


    SELECT *
      FROM planet_osm_point
      WHERE place = 'town'
        AND CASE WHEN population ~ '^[0-9]+$' THEN population::int > 4000 ELSE false END
    ;
    Ответ написан
  • SQL Как из перечня свойств выбрать строки по двум совпавшим?

    erge
    @erge
    Примус починяю
    Т.к. СУБД не указана, то в целом решение примерно такое
    1. либо - искомую строку разбиваем на строки (в таблицу) объединяем с исходной таблицей и ищем вхождение каждого параметра (из "разбитой" в таблицу строки) через функцию поиска подстроки, далее группируем и применяем HAVING count(1) >= 2
    2. либо наоборот - каждую строку параметров исходной таблицы разбиваем получаем таблицу матрицу параметров, далее ищем вхождение параметров в искомой строке, и так же группируем и применяем HAVING count(1) >= 2

    надеюсь понятно изложил...

    и опять таки , т.к. СУБД не указана, то применительно к MS SQL это будет выглядеть вот так:

    1.
    WITH f AS (
      SELECT 'PARAM1 PARAM3 PARAM7' as findstr
    ),
    fr AS (
      SELECT t.value AS param
        FROM f
        CROSS APPLY STRING_SPLIT(f.findstr, ' ') t
    )
    SELECT d.id, count(1) AS num_matches
      FROM data d
      CROSS JOIN fr
      WHERE charindex(fr.param, d.parameters) > 0
      GROUP BY id
      HAVING count(1) >= 2
    ;


    2.
    WITH f AS (
      SELECT 'PARAM1 PARAM3 PARAM7' as findstr
    )
    SELECT d.id, count(1) AS num_matches
      FROM data d
      CROSS APPLY STRING_SPLIT(d.parameters, ' ') ds
      JOIN f ON 1=1
      WHERE charindex(ds.value, f.findstr) > 0
      GROUP BY d.id
      HAVING count(1) >= 2
    ;


    см. пример на dbfiddle

    PS: относительно других СУБД все примерно так же + - , синтаксис другой может быть и наличие аналога функции STRING_SPLIT
    Ответ написан
    Комментировать
  • Как заменить двойные кавычки на "?

    erge
    @erge
    Примус починяю
    Нужно сначала разбить текст на группы attribute_name="attribute_value" затем для этих групп вызвать замену и это можно сделать при помощи preg_replace_callback

    регулярка для поиска ([^= ]+)="(.*?)"\s+(?=([^= ]+=|\/>))
    см. RegEx101

    используем ее в preg_replace_callback, находим пары атрибут=значение и заменяем , делая подмену символов в значении через htmlspecialchars

    $str = '
    <order acode="7102774" ProductName="Какой-то текст "с скобочками", которые нужно заменть" ClientBarCode="" />
       <order acode="7102774" ProductName="Какой-то текст "с скобочками", которые нужно заменть" ClientBarCode="" />
     <order acode="7102774" ProductName="Какой-то текст "с скобочками", которые нужно заменть" ClientBarCode="" />
          <order acode="7102774" ProductName="Какой-то текст "с скобочками", которые нужно заменть" ClientBarCode="" />';
    
    $out = preg_replace_callback(
        '/([^= ]+)="(.*?)"\s+(?=([^= ]+=|\/>))/',
        function($m) {
            return $m[1].'="'.htmlspecialchars($m[2], ENT_QUOTES).'" ';
        },
        $str);
        
    echo $out;


    см. пример
    Ответ написан
    Комментировать
  • Как удалить переносы строк в файле?

    erge
    @erge
    Примус починяю
    echo|set /p= > "%NewFileName%"
    for /f "usebackq tokens=*" %%i in ("%filename%")  do (echo|set /p="%%i" >> "%NewFileName%")
    Ответ написан
    Комментировать
  • Как написать SQL запрос для выборки записей, который учитывает кол-во существующих в таблице записей с таким же ключом?

    erge
    @erge
    Примус починяю
    т.к. набор характеристик может быть совершенно разнообразным, а известен нам только товар (его id), то сопоставлять необходимо по набору характеристик и их кол-ву, т.е. объединяем таблицу саму с собой, из первой выбираем наш продукт и по его набору характеристик соединяем со второй, при этом исключаем исходный товар из второй, как-то так:

    WITH param AS (
      SELECT 5 AS prod_id -- ИД продукта которому ищем сопутствующие
    )
    SELECT p2.prod_id
      FROM param, prod_ch_val p1, prod_ch_val p2
      WHERE p1.prod_id = param.prod_id   -- ИД продукта
        AND p1.ch_id=p2.ch_id
        AND p1.val = p2.val
        AND p1.prod_id != p2.prod_id
        AND (SELECT count(1) FROM prod_ch_val t WHERE t.prod_id=p2.prod_id) = (SELECT count(1) FROM prod_ch_val t WHERE t.prod_id=p1.prod_id)
    GROUP BY p2.prod_id


    пример
    идентичные товары:
    1 и 3
    2 и 5
    4 - не идентичен ни с кем.

    PS: выражение WITH можно убрать и подставлять ID товара непосредственно в запрос вместо param.prod_id
    сделал для удобства
    Ответ написан
    Комментировать
  • Как с помощью sed в bash конвертировать className из camelCase в dash?

    erge
    @erge
    Примус починяю
    например как-то так:
    sed -r '
    s/(className="[^"]+)([A-Z])([^"]+)([A-Z])([^"]+)([A-Z])([^"]+")/\1-\L\2\3-\L\4\5-\L\6\7/g;
    s/(className="[^"]+)([A-Z])([^"]+)([A-Z])([^"]+")/\1-\L\2\3-\L\4\5/g;
    s/(className="[^"]+)([A-Z])([^"]+")/\1-\L\2\3/g
    ' input_file > output_file


    или вот так, во всех файлах по маске:
    sed -i -r '
    s/(className="[^"]+)([A-Z])([^"]+)([A-Z])([^"]+)([A-Z])([^"]+")/\1-\L\2\3-\L\4\5-\L\6\7/g;
    s/(className="[^"]+)([A-Z])([^"]+)([A-Z])([^"]+")/\1-\L\2\3-\L\4\5/g;
    s/(className="[^"]+)([A-Z])([^"]+")/\1-\L\2\3/g
    ' *.jsx

    см. пример
    PS:
    ключ -i[SUFFIX], --in-place[=SUFFIX]
    edit files in place (makes backup if SUFFIX supplied)
    Ответ написан
    2 комментария
  • Удалить символы переноса строки?

    erge
    @erge
    Примус починяю
    sed -r ':a;N;$!ba;s/([^;][^\?])[\r\n]+/\1/g' source_file > target_file


    см. пример на sed.js.org

    пример на regex101, в разделе Explanation - разъяснение шаблона

    PS: если в строке меньше 2 символов, то шаблон не сработает, далее сами развивайте
    Ответ написан
    Комментировать
  • Как массово заполнить таблицу?

    erge
    @erge
    Примус починяю
    Если совсем все сложно с решением выше, хотя оно рабочее (пробуйте разные редакторы, выбирайте какой вам больше подойдет, читайте про регулярные выражения, я не знаю как без них вообще жить ))))

    делайте все из командной строки - скачайте утилиты командной строки sqlite - https://www.sqlite.org/download.html
    Precompiled Binaries for Windows
    sqlite-tools-win32-x86-3410000.zip
    распаковываете утилиты куда вам удобно, прописываете в переменную PATH, ну или например распакуйте в c:\bin

    копируете файл в папку с вашей бд sqlite
    далее запускаете sqlite3.exe в 'этой папке (в консоли, в командной строке!) указывая ему вашу БД, например

    sqlite3.exe my_example_db.sqlt

    далее в командной строке самой sqlite пишете
    create table ru_word (word varchar(100), freq INT);


    PS: порядок полей такой, потому что в файле такой порядок и он грузится как есть, для БД порядок не важен.
    далее

    далее указываете сеператор (разделитель полей в текстовом файле)
    .separator " "
    грузите файл в таблицу
    .import ru_50k.txt ru_word

    все!

    в итого будет примерно так (в командной строке!):
    : переходим в папку с БД, там же должен быть файлru_50k.txt
    cd C:\tmp
    
    : открываем БД в sqlite3
    c:\bin\sqlite3.exe my_example_db.sqlt
    SQLite version 3.41.0 2023-02-21 18:09:37
    Enter ".help" for usage hints.
    sqlite> create table ru_word (word varchar(100), freq INT);
    sqlite> .tables
    ru_word
    sqlite> .separator " "
    sqlite> .import ru_50k.txt ru_word
    sqlite> SELECT count(*) FROM ru_word;
    50000
    sqlite> SELECT MAX(freq) FROM ru_word;
    3854593
    sqlite> SELECT * FROM ru_word LIMIT 10;
    я 3854593
    не 3244771
    что 2665565
    в 2212420
    и 2179689
    ты 2067418
    это 1999607
    на 1240437
    с 1128276
    он 966203
    sqlite> .quit


    PPS: научитесь пользоваться поиском, например загрузка csv в sqlite и т.п. и т.д. etc
    Ответ написан
    1 комментарий
  • Как узнать курс валюты в командной строке терминала?

    erge
    @erge
    Примус починяю
    curl + awk
    curl -s https://www.cbr.ru/scripts/XML_daily.asp | awk -F '</Valute>'  '{for (i=1; i<=NF; i++) if($i ~ /USD|EUR/) print substr($i, index($i, "CharCode")+9,3)" "substr($i, index($i, "Value")+6,7)}' 2>/dev/null


    wget + awk
    wget -qO- https://www.cbr.ru/scripts/XML_daily.asp | awk -F '</Valute>'  '{for (i=1; i<=NF; i++) if($i ~ /USD|EUR/) print substr($i, index($i, "CharCode")+9,3)" "substr($i, index($i, "Value")+6,7)}' 2>/dev/null


    Perl
    perl -MLWP::Simple -e '$_=get("https://www.cbr.ru/scripts/XML_daily.asp");while(m/(USD|EUR).+?Value>([^<]+)/g){print "$1 $2\n"}'


    Python
    python3 -c 'import requests,re;print("\n".join([" ".join(i.groups()) for i in list(re.finditer(r"(USD|EUR).+?Value>([^<]+)", requests.get("https://www.cbr.ru/scripts/XML_daily.asp").text))]))'


    PowerShell
    # вариант 1 (RegEx)
    (Invoke-WebRequest -UseBasicParsing -URI 'https://www.cbr.ru/scripts/XML_daily.asp').Content | Select-String '(USD|EUR).+?Value>([^<]+)' -AllMatches | foreach {$_.Matches.Groups[1,2,4,5].Value}
    # вариант 2 (XML/XPath)
    ([xml](Invoke-WebRequest -UseBasicParsing -URI 'https://www.cbr.ru/scripts/XML_daily.asp').Content).SelectNodes('//Valute[CharCode="USD" or CharCode="EUR"]') | ft Name,Value


    JavaScript (Node.js)
    node -e "https.get('https://www.cbr.ru/scripts/XML_daily.asp',r=>{s='';r.on('data',d=>s+=d);r.on('end',()=>[...s.matchAll(/(USD|EUR).+?Value>([^<]+)/g)].forEach(e=>console.log(`${e[1]} ${e[2]}`)))})"
    Ответ написан
    Комментировать
  • Как заполнить таблицу в цикле Mysql?

    erge
    @erge
    Примус починяю
    т.к. вы не указали версию БД, то предлагаемое ниже решение написано в рамках 8+ версии
    предполагаю что product_attr_id - это автоинкрементный PRIMARY KEY
    В итого, все делается одним запросом и без циклов.
    делаем две рекурсивные CTE (см. Recursive Common Table Expressions), реализуем в них "счетчики", объединяем их и получаем желаемое, далее дело техники, в итого получаем

    INSERT INTO product_attr (attr_7, attr_29)
    WITH RECURSIVE
      param AS
    (
      SELECT
        461  AS attr_7_start,  -- начальное значение для attr_7
        10   AS attr_7_num,    -- количество итераций в attr_7
        1097 AS attr_29_start, -- начальное значение для attr_29
        3    AS attr_29_num    -- количество итераций в attr_29
    ),
      attr29_iter (n) AS
    (
      SELECT 0
      UNION ALL
      SELECT n + 1 FROM attr29_iter, param WHERE n < attr_29_num -1
    ),
     attr_7_iter (n) AS
    (
      SELECT 0
      UNION ALL
      SELECT n + 1 FROM attr_7_iter, param WHERE n < attr_7_num -1
    ),
      gen_inc AS
    (
      SELECT i7.n as inc7, i29.n as inc29
        FROM attr_7_iter i7, attr29_iter i29
    )
    SELECT attr_7_start + inc7, attr_29_start + inc29
      FROM gen_inc, param
      ORDER BY 1,2
    ;


    PS: для удобства, вынес так называемые параметры в отдельную CTEшку param

    см. пример на dbfiddle

    UPDATE:
    для "прохода" по нескольким продуктам по их категориям, просто включаете таблицы product и category в общее объединение во внешнем запросе SELECT

    INSERT INTO product_attr (product_id, product_price, product_old_price, attr_7, attr_29)
    WITH RECURSIVE
      param AS
    (
      SELECT
        461  AS attr_7_start,  -- начальное значение для attr_7
        14   AS attr_7_num,    -- количество итераций в attr_7
        1097 AS attr_29_start, -- начальное значение для attr_29
        3    AS attr_29_num    -- количество итераций в attr_29
    ),
      attr29_iter (n) AS
    (
      SELECT 0
      UNION ALL
      SELECT n + 1 FROM attr29_iter, param WHERE n < attr_29_num -1
    ),
     attr_7_iter (n) AS
    (
      SELECT 0
      UNION ALL
      SELECT n + 1 FROM attr_7_iter, param WHERE n < attr_7_num -1
    ),
      gen_inc AS
    (
      SELECT i7.n as inc7, i29.n as inc29
        FROM attr_7_iter i7, attr29_iter i29
    )
    SELECT p.product_id, p.product_price, p.product_old_price, attr_7_start + inc7 AS attr_7, attr_29_start + inc29 AS attr_29
      FROM gen_inc, param, product p, category c
      WHERE p.product_id = c.product_id
        AND c.category_id NOT IN (214, 221, 220, 217, 216, 215, 48, 42, 40, 45, 46, 44, 50, 41, 43, 31, 178, 89, 47, 179, 177, 120, 121, 59, 58, 32, 37, 56, 53, 54, 55, 29, 28, 30, 176, 237, 113, 116, 175, 114, 196, 195, 197, 218, 219, 33, 93, 92, 91, 81, 90)
      ORDER BY 1, 4, 5
    ;


    см. пример на dbfiddle
    Ответ написан