Ответы пользователя по тегу MySQL
  • Как правильно вывести записи из бд(MySql,PHP)?

    @alexalexes
    Накопите промежуточные строки в $out_arr, соедините элементы массива через разделитель join-ом и подайте на вывод.
    $out_arr = array(); 
    while($hero2 = mysqli_fetch_assoc($hero1))
        {
         
    $time_now = strtotime($hero2['cron1']);
    $time_need = strtotime($hero2['cron2']);
    if($time_need>=$time_now ){
    $t_s= date("H:i ",75600-($time_need-$time_now));
    }
    else
    $t_s= date("H:i ",75600-($time_now-$time_need));
           $out_arr[] = str_replace(":",".",$t_s);
     }
    echo "[".join(' ,',  $out_arr).']';
    Ответ написан
    Комментировать
  • Как реализовать такую выборку SQL?

    @alexalexes
    То есть, если у вас свойство count меньше 3, то выводить для таких позиций count = 0?
    SELECT shop_product.id, if(shop_product_skus.count >= 3, shop_product_skus.count, 0) as count
      FROM shop_product
        join shop_product_skus on shop_product.id = shop_product_skus.product_id 
    WHERE 
        shop_product.id IN (14770, 13287, 14160, 13906)
    Ответ написан
    1 комментарий
  • Какая лучшая практика наименования полей таблицы в MySQL?

    @alexalexes
    Тут дело выбора стандартов внутри группы разработчиков, как договоритесь использовать имена.
    Например, второй способ избыточен при таком подходе написания запросов.
    select country.country_id
    from country

    а вот здесь чуть полегче разобраться к чему относиться псевдоним таблицы:
    select c.country_id
    from country c

    Если умело сокращать имена псевдонимов, то жить можно и при кратком подходе именования:
    select ctry.id
    from country ctry

    Если загвоздка иного рода - именовать поле country_id или id_country.
    Первый вариант правильный с точки зрения англ. языка, а второй - визуально легче отслеживать виды полей, если их записать вертикально.
    Ответ написан
    Комментировать
  • Как оптимально получить симметричные данные в таблице?

    @alexalexes
    Элементарно, заджойнте ту же самую таблицу саму на себя.
    select *
    from t as t1
    join t as t2 on t1.user_id1 = t2.user_id2
                     AND t2.user_id1 = t1.user_id2
    Ответ написан
    2 комментария
  • Как посчитать количество дней с учетом всех выходных в MySQL?

    @alexalexes
    select count(*) as work_day_count --считаем, что осталось после отсечения выходных и праздников
      from (SELECT distinct t1.*, t1.c1 + INTERVAL iterator.day DAY as dt_day
                 FROM (select STR_TO_DATE("01.10.2018", "%d.%m.%Y") c1,  STR_TO_DATE("22.10.2018", "%d.%m.%Y") c2 union all
                       select STR_TO_DATE("22.10.2018", "%d.%m.%Y") c1,  STR_TO_DATE("10.11.2018", "%d.%m.%Y") c2 ) t1 --таблица с проверяемыми интервалами
     
     join (select @start_day := @start_day + 1 as day
             from news,  -- любая произвольная таблица с числом строк, больше чем ширина максимально возможного интервала дней, который можно рассмотреть этим запросом
                  (select @start_day := -1) init_day --инициализация переменной start_day 
          ) iterator --итератор дней, ведет отсчет с 0 и до куда надо (до максимального интервала, который может быть)
       on (t1.c1 + INTERVAL iterator.day DAY) <= t1.c2 --верхнее ограничение итератора
                    and (t1.c1 + INTERVAL iterator.day DAY) not in -- отсекаем выходные и праздники
    (select STR_TO_DATE("06.10.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("07.10.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("13.10.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("14.10.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("20.10.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("21.10.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("27.10.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("28.10.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("03.10.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("04.11.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("10.11.2018", "%d.%m.%Y") c1 union all
     select STR_TO_DATE("11.11.2018", "%d.%m.%Y") c1) -- тут делаем выборку выходных дней и праздников
    order by dt_day ) a
    Ответ написан
    Комментировать
  • Как лучше сделать парсер данных с разных источников?

    @alexalexes
    В вашей схеме еще не хватает подсистемы scheduler - планировщик заданий.
    Его нужно чаще всего запускать по крону (а может он у вас будет вертеться в бесконечном цикле, а может спать в потоковом режиме выполнения).
    Планировщик, на основе результатов проходов паука, парсера, ограничений на проходимых сайтах, нагрузки собственной системы, будет регулировать частоту запуска перезапуска заданий.
    Желательно, чтобы задания паука и парсера были достаточно атомарны.
    Паук в одну страницу постучал, записал статус получения ответа, каков контент в ответе (html или текстовое сообщение, или JSON и тд.), удалось ли ему распознать структуру, метаданные и тд.
    Если, например, вернулась 404 стр, то возможно, с помощью планировщика установить правило, что можно натравить паука на url чуть позже, через час, день, неделю и тд.
    По аналогии, можно фиксировать статусы работы других подсистем checker-а, парсера.
    Если один из модулей застревает на 5 разе на каком-то задании, то сыпать критическую ошибку в лог и тд.

    В общем, каков бы состав модулей не был, но планировщик нужен.
    Ответ написан
    Комментировать
  • Как сгруппировать диалоги по двум полям в MySQL через GroupBY?

    @alexalexes
    Пробуйте этот запрос с вычисленным псевдопараметром dialog_hold.
    Суть в том, что этот параметр одинаковый для переписки пользователя 1 и пользователя 2 в ту и другую сторону.
    Должно получаться число 1000002 при sender_id=1, recipient_id=2 и при sender_id=2, recipient_id=1.
    По этому параметру можно отсортировать переписку так, чтобы беседы пользователей шли по порядку.
    Значение 1000000 должно быть заведомо большое, чем возможно число пользователей в вашей системе в любой исторический период. Однако, max(user_id) * 1000000 + max(user_id) никогда не должно превышать макс. целочисленное значение, с которым может работать СУБД (верхний предел id пользователей, когда этот финт ушами способен работать).
    select a.*
    from (select d.id, d.tovar_id, d.sender_id, d.recipient_id, d.message,
                 case
                   when d.sender_id < d.recipient_id
                   then d.sender_id * 1000000 + d.recipient_id
                   else d.recipient_id * 1000000 + d.sender_id
                 end dialog_hold
            from dialogs d
           where d.tovar_id = :tovar_id
             and (d.sender_id = :user_id or d.recipient_id = :user_id)
          ) a
    order by  a.tovar_id, a.dialog_hold, a.id
    Ответ написан
  • Как удалить нужную запись из БД?

    @alexalexes
    Если заняться изучением основ SQL, то можно понять, что в данной ситуации самым оптимальным решением будет - выполнить запрос с параметром:
    DELETE FROM videos WHERE id = ?
    Естественно, на странице браузера надо обеспечить, чтобы при нажатии кнопки "Удалить" серверу передавался id удаляемой записи, помимо того, какое действие мы хотим совершить.
    Серверный скрипт, также должен принимать не только параметр вида действия (delete), но параметр id, на какую запись необходимо направить действие. Далее, структура SQL-запроса должна иметь в себе возможность подставить параметр.
    PS:
    $ids = R::getAssoc('SELECT id FROM videos');
        $videos = R::find( 'videos', 'id = ?', $ids );

    Самое не оптимальное решение - выгребать все записи из таблицы, а потом на стороне серверного приложения искать ту единственную, которая удовлетворяет условию. Эта медвежья услуга нагружает тракт обмена данных между веб-сервером и СУБД-сервером.
    Ответ написан
    Комментировать
  • Как осуществить выборку MySQL?

    @alexalexes
    А зачем вам куча запросов? Нужен всего один, но с параметрами и мат. функциями.
    Чистая математика, ничего лишнего.
    SELECT *
    FROM points p
    WHERE sqrt(pow(p.x - :x, 2) + pow(p.y - :y, 2)) <= :r -- используем формулу определения расстояния между двумя точками, параметры запроса, которые нужно задать :x, :y, :r.
    Ответ написан
  • Как обойти ошибку при добавлении столбца в БД?

    @alexalexes
    При создании нового столбца, вероятно, вы указываете значение по умолчанию, и вероятно, пытаетесь использовать значение 0 для даты. Хотя, если используется значение по умолчанию, его нужно задавать корректно с точки зрения эпохи Unix (от 01.01.1970 и моложе).
    Ответ написан
  • PhpMyAdmin. Появляется ошибка из-за php_max_input_vars. Как исправить?

    @alexalexes
    max_input_vars = 10000000000000000000000000000000000000

    Серьезно. )))) И в какой тип данных среда должна положить это значение, чтобы потом проверять лимит?
    Вы хоть в пределах одного порядка поэспериментируйте, 3000... 5000.
    Ответ написан
  • Как сохранять timestamp из php в MySQL?

    @alexalexes
    Используйте функцию FROM_UNIXTIME для преобразования входных параметров в тип данных timestamp:
    INSERT INTO you_table (expiration_date) VALUES (FROM_UNIXTIME('1526763600'))

    Проверяем результат:
    SELECT UNIX_TIMESTAMP(expiration_date) FROM you_table
    Ответ написан
    2 комментария
  • Правильный запрос к MySQL?

    @alexalexes
    Запрос выполнился. $res не хранит выборку.
    Выборку надо вытянуть fetch-функцией.
    Ответ написан
    Комментировать
  • Как из базы MySQL вывести данные в Android Studio?

    @alexalexes
    Между вашим клиентским приложением и MySQL должно быть серверное приложение, которое будет непосредственно выполнять запросы на MySQL и предоставлять данные и API вашему приложению.
    Легче всего поднять PHP или node.js сервер и связать его с MySQL, обмен данными с клиентом - в JSON формате.
    Ответ написан
    Комментировать
  • Как вывести много вложений вместе с постами?

    @alexalexes
    Я обычно выгребаю всю вложенность одной портянкой (добиваемся уникальности имен полей, добавляя необходимые префиксы):
    Select p.id as post_id, p.create_date as p_create_date, p.title as p_title, p.text as p_text,
               img.id as img_id, img.name as img_name,
              v.id as v_id, v.name as v_name
    from posts p
    left join images img on img.post_id = p.id
    left join videos v on v.post_id = p.id

    А потом в PHP собираю ассоциативный массив с нужной глубиной вложенности:
    $out = [];
    foreach($rows as $row)
    {
      $post = &$out[$row['POST_ID']]; //ссылка на элемент массива первого уровня - пост
      $post['CREATE_DATE'] = $row['P_CREATE_DATE'];
      $post['TITLE'] = $row['P_TITLE'];
      $post['TEXT'] = $row['P_TEXT'];
       if(!is_null($row['IMG_ID']))  
      {
          $image = &$post['IMAGES'][$row['IMG_ID']]; //ссылка на элемент массива второго уровня - элемент массива изображений
          $image['NAME'] = $row['IMG_NAME'];
      }
       if(!is_null($row['V_ID']))  
      {
         $video = &$post['VIDEOS'][$row['V_ID']]; //ссылка на элемент массива второго уровня - элемент массива видео
          $video['NAME'] = $row['V_NAME'];
      }
    }

    На выходе получаем $out - вполне себе структуированный объект, пригодный для дальнейшей обработки и выдачи на фронтенд.
    PS: Использование ссылок ускоряет сборку таких структур.
    Например, чтобы заполнить несколько свойств элемента массива IMAGES, который вложен, быстрее будет отрабатывать конструкция:
    $post = &$out[$row['POST_ID']];
    $image = &$post['IMAGES'][$row['IMG_ID']];
    $image['NAME'] = $row['IMG_NAME'];
    $image['WIDTH'] = $row['IMG_WIDTH'];
    $image['HEIGHT'] = $row['IMG_HEIGHT'];


    Чем вот такое нагромождение для заполнения каждого свойства:
    $out[$row['POST_ID']]['IMAGES'][$row['IMG_ID']]['NAME'] = $row['IMG_NAME'];
    $out[$row['POST_ID']]['IMAGES'][$row['IMG_ID']]['WIDTH'] = $row['IMG_WIDTH'];
    $out[$row['POST_ID']]['IMAGES'][$row['IMG_ID']]['HEIGHT'] = $row['IMG_HEIGHT'];
    Ответ написан
  • Какие лучше сделать отношения между таблицами?

    @alexalexes
    Упражнение
    (# Id -- идент. упражнения
    * Grp_Id -- идент. группы мышц, внеш ключ
    * Name -- Название,
    * Descr -- Описание
    )

    Мышцы
    (# Id -- идент. мышцы,
    * Grp_Id -- идент. группы мышц, внеш. ключ,
    * Name -- Название
    )

    Группа мышц
    (# Id -- идент. группы мышц,
    * Name -- Название
    )

    Воздействие упражнения
    (# Id -- идент. воздействия,
    * Ex_Id -- идент. упражнения, внеш. ключ
    * Мus_Id -- идент. мышцы, внеш ключ
    * Power -- сила воздействия или просто целевой флаг
    )

    Если вы говорите про связь "много-много", то знайте, что за ней прячется еще одна табличка, реализующая ассоциативную связь между основными объектами, и по сути это две связи через таблицу. В вашем случае, это Воздействие упражнения. Если взять концепцию графа ("много-много" - это всегда граф, а точнее его ребрышки). То, упражнения и мышцы - это вершины графа, а ребра - это как раз пары [ex_id, mus_id], вес ребра - сила воздействия. В этой же табличке можно было бы хранить ребра воздействий на группы мышц [ex_id, grp_id], в этом случае mus_id будут заполнены null-значениями, но задание говорит, что нужно связать группы мышц с упражнениями.
    Ответ написан
  • Как сформировать запрос MySQL?

    @alexalexes
    Изучите для начала как использовать MAX(), SUM(), NUMBER() в mySQL.
    Потом попробуйте эмулировать конструкции:
    Max() over (partition by ... )
    Sum() over (partition by ... )
    Rank() over (partition by ... order by ... )
    Ощутите всю "прелесть" mySQL по сравнению с MS SQL, Oracle и прочими СУБД, которые умеют эти конструкции.
    select b.id, b.name, b.sum_value, b.max_date -- а в самом конечной выборке выбираем только первые номера нумерации строк от каждого человека
    from ( select a.id, a.name, a.sum_value, a.max_date,  -- в этом подзапросе нумеруем строки в пределах одного человека
                          @rank := IF(@name2 != a.name, 1, @rank + 1) as rnk,
                          @name2 := a.name
                  from (select t.id, t.name,  -- в этом подзапросе находим сумму очков и максимум даты
                              @sum := IF(@name != name, value, @sum + value) as sum_value,
                              @max := IF(@name != name, date, @max) as max_date,
                              @name := name
                      from   
                                 (select 1 id, 'Вася' Name, 7 value, STR_TO_DATE('01.01.2018', '%d.%m.%Y') date union all
                                  select 2 id, 'Вася' Name, 2 value, STR_TO_DATE('02.02.2018', '%d.%m.%Y') date union all
                                  select 3 id, 'Петя' Name, 2 value, STR_TO_DATE('01.01.2018', '%d.%m.%Y') date union all
                                   select 4 id, 'Вова' Name, 2 value, STR_TO_DATE('01.01.2018', '%d.%m.%Y') date ) t, --исходные данные в виде таблицы t
                                 (select @max := 0, @sum := 0, @name := '') p
                      order by t.name, date desc
                     ) a,
                      (select @rank := 1, @name2 := '') p2
                      order by a.name, a.sum_value desc
    ) b where b.rnk = 1
    order by b.id, b.name
    Ответ написан
  • Как изменить значения в одной таблице, взяв значения из другой?

    @alexalexes
    А где первичные ключи в табличках?
    Вообще, если таблицы - некие копии друг друга, то обновления записей проворачивают как-то так.
    update tab1 t1, tab2 t2   // таблицы, участвующие в Update
    set  t1.key = ?                      // устанавливаем параметр key, только непонятно, что задаем
    where t1.id = t2.id          // соответствие записей по первичным ключам

    Если нужно сделать сложное обновление, сопоставив некую совокупность атрибутов, не привязываясь к ключам, то как-то так.
    update tab1 t1, tab2 t2   // таблицы, участвующие в Update
    set t1.key = ?                      // устанавливаем параметр key, только непонятно, что задаем
    where t1.SecondName = t2.SecondName // допустим, пусть будет обновление key у тех записей, у которых есть полное соответствие атрибутов.
       and t1.LastName = t2.LastName
      and t1.ThirdName = t2.ThirdName
    Ответ написан
    Комментировать
  • Копирование таблиц в базе данных?

    @alexalexes
    Вы хотели сказать столбцы?
    Добавьте их в структуру, куда нужно перенести значения, с null опциональностью.
    ALTER TABLE test2.board ADD data_razm datatime null AFTER moder;
    ALTER TABLE test2.board ADD ip        tinytext null AFTER data_razm;


    А потом сделайте сложное обновление
    update test2.board t2b, test.board tb
    set t2b.data_razm = tb.data_razm,
          t2b.ip = tb.ip
    where t2b.id = tb.id


    Наверняка, еще в реальном времени данные в таблице изменяются.
    В этом случае нужно создавать триггеры, чтобы они синхронизировали изменения в этих таблицах.
    Если есть реальное время, то сначала делаем триггеры, а потом сложное обновление.
    Ответ написан
    Комментировать
  • Может ли MySQL 5.7 принимать в процедуры и INSERT-запросы VARCHAR-переменные в сыром виде (сырые строки)?

    @alexalexes
    Строка запроса при обработке SQL интерпретатором уже будет рассматриваться синтаксическим аппаратом SQL, в нем уже не отличишь, что реально имели ввиду, когда подставляли параметры.
    Предобработка такой строки регулярными выражениями, хоть может дать толк на отдельных тестовых примерах, но не убережет вас от sql-инъекций.
    Разработчик внешнего приложения должен быть сурово наказан за то, что формирует запрос вот так:
    $sql = "insert into table_name(name) value('".$str_param."')";

    А его приложение должно быть исключено из продакшена, как содержащее уязвимость, позволяющее атаковать sql-инъекциями, до того как не будет внесен фикс такого плана во всех случаях (!!!), где приложение контактирует с СУБД, а не только в этом запросе:
    $sql = "insert into table_name(name) value(:param1)";  //текст запроса с метками для вставки параметров;
    $prep_sql = $sqlconnect->prepare($sql); //подготовка SQL-запроса, фактически, синтаксический разбор и выявление меток, куда вставлять параметры, проверка ошибок;
    $prep_sql->bindParam('param1', $str_param, STRING_TYPE); //связываем параметры с метками в запросе, проверяем тип входного параметра;
    $prep_sql->execute(); //выполняем запрос

    PS: Последний пример написан на псевдокоде, но посыл должен быть понятен.
    Ответ написан
    Комментировать