Задать вопрос
Ответы пользователя по тегу MySQL
  • Нубский вопрос: что произошло при false?

    @alexalexes
    Вы путаете уровни абстракции, на которых можно получать исключения (ошибки).
    С точки зрения обмена данных между клиентом СУБД и СУБД не будет ошибкой, если СУБД вернет пустую выборку при корректно отправленном запросе клиентом и при корректном выполнении плана выполнения запроса со стороны СУБД.
    Но для бизнес-логики, для которой вы пытаетесь обозначить ошибку, наверное, будет существенно, отсутствие выборки. На этом уровне вы сами должны оценить результат запроса в PHP коде и сгенерировать исключение по бизнес-логике.
    Ответ написан
    7 комментариев
  • Нужно составить запрос если?

    @alexalexes
    if ($result->num_rows > 0 && $order['status_cart'] == 'Ожидает оплаты')
    {
      // do something
    }

    Вообще, замените ваш enum на атрибуте status_cart на числовой id статуса. Сделайте отдельную таблицу - "Статус оплаты" и пропишите там все значения, сошлитесь на эту таблицу внешним ключом.
    Если не хотите отказаться от enum, то используйте английские наименования, иначе вам придется гарантировать, что вы протащите кириллицу на все скрипты (чтобы везде был utf-8 в том числе при передачи данных в API).
    Ответ написан
    2 комментария
  • Устанавливать ли в php таймзону пользователя?

    @alexalexes
    Проблем с временными зонами вообще не будет, если их представление выдавить максимально ближе к модели представления данных на интерфейсе пользователя.
    Нужно конвертировать в строку только непосредственно перед отрисовкой дату и время из UTC, и обратно загонять время в UTC, если забираете пользовательский ввод.
    Весь бек должен работать в одной временной зоне, а от пользователя знать, что он в такой-то временной зоне, только в контексте сессионной переменной, если это необходимо.
    Ответ написан
    Комментировать
  • Как правильно сформировать SQL запрос?

    @alexalexes
    select a.*
    from (
    select s.*,
              row_number() over (partition by `customer_id` order by unit_importance, updated_at desc) rn
      from stream s
    ) a
    where a.rn = 1

    Единственное, у вас MySQL должен быть 8+ версии. А если 5-ой версии, то ищите аналог оконной функции.
    Ответ написан
    4 комментария
  • Есть ли разница в производительности при запуске функции ил SQL запроса или в цикле php?

    @alexalexes
    1. На 3-10 позициях не имеет значения реализация.
    2. На 100...1 млн лучше экономить трафик между PHP сервером и СУБД.
    3. Если нельзя избежать транссистемой обработки задачи на 100...1 млн, то разбивайте задачу на пакеты в 100...1000 ед. Пакеты ставьте в очередь на обработку. Делайте диспетчер очереди.

    В общем, какой бы замер не сделали бы. Вы придете к одному из этих решений.
    Ответ написан
    Комментировать
  • Как найти минимальное свободное значение в диапазоне?

    @alexalexes
    WITH RECURSIVE
    -- Тестовая выборка. Если есть "живая" таблица, то эту выборку можно убрать  
     t as (select 10.000 value union
               select 10.001 union
               select 10.002 union
               select 10.003 union
               select 10.005 union
               select 10.009 -- специально добавил контр. пример
              ),
    -- Таблица-генератор последовательности чисел от min(t.value) до max(t.value) с шагом 0.001 с помощью CTE (есть ограничение по глубине рекурсии!)
    num_series AS (
      SELECT (select min(value) from t)  AS num
      UNION ALL
      SELECT num + 0.001 FROM num_series
       WHERE num < (select max(value) from t)
    )
    -- Запрос, в котором сопоставляем таблицу генератор и исходную таблицу, чтобы найти недостающие кванты
    SELECT * 
      FROM num_series
     where not exists(select t.value from t where t.value = num_series.num)
         and num_series.num >= 10.000

    PS: Нужен MySQL 8 версии и выше, postgres, или СУБД из интерпрайзного сегмента.
    Ответ написан
  • Из-за чего возникает ошибка mysql при создании таблицы?

    @alexalexes
    ... `key` INT ...
    В обратные кавычки берите названия колонок, потому что без них key будет восприниматься интерпретатором как ключевое слово.
    Ответ написан
    Комментировать
  • Как вывести подсчёт статистики из базы данных?

    @alexalexes
    Несколько Count + умение обращаться с временнЫми функциями, и у вас получится универсальный запрос со статистикой:
    Если scv.date типа date или datetime:
    select count(case when scv.date >= CURDATE() then 1 end) today_count,
           count(case when scv.date >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) and scv.date < CURDATE() then 1 end) yesterday_count,
           count(case when scv.date >= DATE_SUB(CURDATE(), INTERVAL 1 WEEK) then 1 end) week_count,
           count(case when scv.date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH) then 1 end) month_count
    from statistics_couter_visit as scv
    where scv.date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH) -- тут ограничение по макс. окну просмотра статистики, то есть по month_count

    Если scv.date типа timestamp (или любое другое целочисленное представление):
    select count(case when scv.date >= UNIX_TIMESTAMP(CURDATE()) then 1 end) today_count,
           count(case when scv.date >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL 1 DAY)) and scv.date < UNIX_TIMESTAMP(CURDATE()) then 1 end) yesterday_count,
           count(case when scv.date >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL 1 WEEK)) then 1 end) week_count,
           count(case when scv.date >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) then 1 end) month_count
    from statistics_couter_visit as scv
    where scv.date >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) -- тут ограничение по макс. окну просмотра статистики, то есть по month_count

    PS: Естественно, по полю scv.date должен быть создан индекс.
    Ответ написан
    24 комментария
  • Какую кодировку выбрать для бд чтобы хранить фото?

    @alexalexes
    В базе данных, обычно, не хранят бинарные данные файлов.
    Кладете на файловый сервер файл, берете путь к этому файлу и записываете в поле таблицы.
    Если очень приспичило какой-то бинарник положить в поле таблицы, то для этого есть binary/varbinary type.
    Но злоупотреблять возможностью записывать безразмерные данные в одно поле не стоит - намучаетесь с бекапами.
    Ответ написан
    Комментировать
  • Как настроить кнопку удаления из бд?

    @alexalexes
    при желании ее удалять

    Скорее очищать данные работы программы. Вряд ли вы держите исходный код программы в таблицах БД, чтобы потом ее удалять.
    Не вполне понятно, как называются таблицы, которые вы хотите очищать (сами таблицы как объекты БД останутся, удалится только их содержимое). Но по вашему фрагменту можно что-то работающее при посте action=delete написать так:
    if(isset($_POST['action']) && $_POST['action'] == 'delete') // есть action и он равен delete
    {
        $link = mysqli_connect($host, $user, $password, $database);
        $sql = "DELETE FROM `program_day_1`"; // по одной инструкции удаления на каждую таблицу
        $res = mysqli_query($link, $sql);
        $sql = "DELETE FROM `program_day_2`";
        $res = mysqli_query($link, $sql);
        mysqli_close($link);
        header('location: program-admin.php');
    }
    Ответ написан
  • Как лучше оптимизировать запрос в базу?

    @alexalexes
    Есть два дилетантских момента построения БД:
    1. Используется строковый тип данных вместо целочисленного на всех полях, где оно используется как идентификатор, (все, что ...id).
    Вероятно, второе следствие наивного проектирования БД:
    2. На поля, которые участвуют в соединении таблиц или в условии фильтрации через where не предусмотрены индексы. По данному запросу сразу просится проверить наличие или создать индексы на:
    `products`.`category_id`, `product_filter_value`.`value_id`, `product_filter_value`.`product_id`.
    Ответ написан
  • Почему разные результаты при проверки вложения (case sensitive)?

    @alexalexes
    Еще явное приведение к типу char работает:
    select instr(convert(json_unquote(json_extract('{"name": "Gamma Electronics"}','$.name')), char), 'ga')
    Ответ написан
    Комментировать
  • В чем может быть причина автоматического созадния столбца в таблице?

    @alexalexes
    Либо в приложении ищите зачатки alter table (не факт, что chat_id добавляют как параметр из какого-нибудь конфига), либо в хранимых процедурах СУБД.
    Ответ написан
  • Как взять каждое значение массива mysqli_fetch_array и занести каждое значение в строку таблицы mySQL?

    @alexalexes
    У вас:
    while($row=mysqli_fetch_array($res))
    {  
        // #########################
        // ####  начало тела цикла  #####
        // ##########################
        $iduser=$id;
        $idkat=$row['idkat'];
         // #########################
        // ####  конец тела цикла  #####
        // ########################## 
    }  
        $res=mysqli_prepare($bd, "INSERT INTO zakaz (iduser,idkat) 
     VALUES(?,?)");
     mysqli_stmt_bind_param($res, 'ii', $iduser,$idkat); // подставляем переменные, которые присвоились на ПОСЛЕДНЕМ прогоне цикла
     $result2=mysqli_stmt_execute($res);

    Как вы ожидаете:
    while($row=mysqli_fetch_array($res))
    {  
        // #########################
        // ####  начало тела цикла  #####
        // ##########################
        $iduser=$id;
        $idkat=$row['idkat'];
        $res2=mysqli_prepare($bd, "INSERT INTO zakaz (iduser,idkat) 
     VALUES(?,?)");
     mysqli_stmt_bind_param($res2, 'ii', $iduser,$idkat); // подставляем переменные, которые присвоились на ТЕКУЩЕМ прогоне цикла
     $result2=mysqli_stmt_execute($res2);
         // #########################
        // ####  конец тела цикла  #####
        // ########################## 
    }

    PS: Есть нюанс. Обработку второго запроса нужно вести по отдельному дескриптору $res2, чтобы не поломать дескриптор $res, по которому работает while.
    Ответ написан
    Комментировать
  • Как составить SQL запрос для отчета с разным количеством строк по категории?

    @alexalexes
    При помощи SQL вы получаете исходные данные, в виде первой таблицы.
    Далее работаете только кодом PHP.
    Вторая таблица - это у вас несколько матриц, по количеству подразделений.
    Одна матрица n*m это:
    n - макс. индекс предмета 000n в пределах одного подразделения.
    m - макс. индекс видов предметов во всей исходной выборке.
    Позиция в матрице i,j:
    i - это 000i
    j - индекс вида предмета.

    Для вывода результата вам нужно получить структуру:
    $result =
    [
      1 =>  // department_id
      [
         1 /* 000i индекс */ => [1 /*индекс вида предмета*/ => '1_1_0001', 2 => '1_2_0001', 3 => '1_3_0001' /* непосредственно данные */],
         2 /* 000i индекс */ => [1 /*индекс вида предмета*/ => '1_1_0002', 2 => '1_2_0002', 3 => '1_3_0002' /* непосредственно данные */],
         3 /* 000i индекс */ => [1 /*индекс вида предмета*/ => '1_1_0003', 3 => '1_3_0003' /* непосредственно данные */],
         ...
      ],
      2 =>
      ...
    ];

    Вариант 2, динамически в PHP создать запрос:
    select t.department_id,
              t1.item as type_1,
              t2.item as type_2,
              ...
    from t
    left join (select t.department_id, t.item from t where t.type_id = 1) t1 on  t1.department_id = t.department_id
    left join (select t.department_id, t.item from t where t.type_id = 2) t2 on  t2.department_id = t.department_id
    ...
    where 1 = 1
        and (SUBSTRING_INDEX(t.item, '_', -1) + 0 = SUBSTRING_INDEX(t1.item, '_', -1) + 0 or t1.item is null)
        and (SUBSTRING_INDEX(t.item, '_', -1) + 0 = SUBSTRING_INDEX(t2.item, '_', -1) + 0 or t2.item is null)
       ...
      -- тут нужно получить равенство всех субиндексов 0000i от t.item сравнить со всеми tn.item
    order by  t.department_id, SUBSTRING_INDEX(t.item, '_', -1) + 0
    Ответ написан
    2 комментария
  • Есть ли готовые решения, для отмены действий на сайте, как бы SQL-undo?

    @alexalexes
    Проектируйте структуру базы данных так, чтобы сохранялась полная история действий над каждым классом данных, словно сохраняете лог для спец. служб.
    Api пользователя не должно использовать DELETE, только INSERT, и UPDATE только для выставления даты удаления записи, выставления метки последней актуальной записи истории. Операцию DELETE имеет право использовать только служебный метод для зачистки истории, когда устаревшие записи становятся неактуальными ни для одного актора системы.
    Ответ написан
    Комментировать
  • Как выбрать данные без дублей с сортировкой?

    @alexalexes
    select A.*
    from (SELECT id, order_id, updated,
                 row_number() over (partition by order_id order by updated DESC) rn
    FROM orders
    WHERE state = 1
    ) A
    where A.Rn = 1
    ORDER BY A.updated DESC
    LIMIT 5, 5
    Ответ написан
    Комментировать
  • Как решить проблему с php?

    @alexalexes
    Во-первых, нужно узнать, где находиться файл error_log, куда сервер пишет ошибки.
    Во-вторых, в любой непонятной ситуации добавляем в начале скрипта принудительное рапортование ошибок в лог и вывод их пользователю в начале скрипта:
    <?php
    error_reporting(E_ALL); // репорт ошибок в файл error_log
    ini_set('display_errors', 'On'); // вывод сообщения об ошибке

    В-третьих, не стесняемся пользоваться функцией var_dump/print_r для любых переменных, где есть сомнения, что они содержат нужные значения.
    var_dump($_POST);
    В-четвертых, при изучении любой библиотеки взаимодействия с СУБД первым делом лезем в справку и ищем, как вывести человекочитаемые ошибки. В PDO это метод errorInfo. Применяем его после любой операции с СУБД - коннектом, подготовкой запроса, выполнением запроса, выборкой результата:
    var_dump($pdo->errorInfo());
    В-пятых, в браузере F12, вкладка "Сеть". Смотрим, а на тот ли адрес идет запрос отправки формы. Изучаем HTTP заголовки, полезную нагрузку, ответ от сервера.

    Вот пример базовых навыков PHP разработчика. Без них можно даже не открывать видосики.
    Ответ написан
    2 комментария
  • Как в Drupal 10 массово проставить noindex для >1000 страниц?

    @alexalexes
    писать скрипт, который будет вытаскивать по запросу необходимые записи, далее для каждой записи разбирать сер.массив, находить нужное значение, изменять его и затем записывать новый массив с изменённым значением в БД

    Именно так. Но лучше найти вариант вытаскивать список статей с помощью объектной модели движка самой CMS, и каммитить сохранение статьи тоже методом из объекта CMS (и не забыть еще дернуть метод очистки кэша страницы, или всего сайта, или части его контекста).
    Если у вас сайт высоконагруженный, то лучше разобраться с объектами CMS. Если нет, или не охота углубляться под капот CMS, то можно самописным скриптом поправить записи в базе, и не забыть сбросить кэш уже в панели управления CMS.
    PS: С drupal не знаком, но в любой CMS проблема будет решаться именно так.
    Ответ написан
    Комментировать
  • Как связать таблицы по одному столбцу и посчитать сумму?

    @alexalexes
    /* создание подготавливаемого запроса */
    $stmt = $mysql->prepare("select sum(c.`Price`) as price_sum
                                 from `dogovor` d
                                 join `catalog` c on c.`Id_Product` = d.`Id_Product`
                              where d.`id_client` = ?");
    /* связывание параметров с метками */
    $stmt->bind_param("i", $id_client);
    /* выполнение запроса */
    $result = $stmt->execute();
    /* выборка результатов */
    $row = $result->fetch_accos();
    if($row)
    {
      echo 'Общая стоимость всех заказов клиента: '.$row['price_sum'];
    }
    else
    {
      echo 'Запрос не дал результата!';
    }

    Ошибки в вашем решении:
    1) Небезопасная подстановка параметров в запросах. Неумение использовать в этой ситуации подготовленные запросы.
    2) Использование id_client как строкового параметра, если он состоит из цифр, то целесообразно использовать целочисленный тип в колонке таблицы.
    3) Неиспользование агрегированных функций среды sql. Зачем на php плодить лишние циклы, когда сумму можно посчитать "из коробки" средствами самой СУБД? Она под это заточена.
    4) Связывание таблиц по наименованию сущности, а не по его идентификатору. Рационально связывать по id_product вместо name_product.
    Ответ написан
    Комментировать