Ответы пользователя по тегу MySQL
  • Почему LIKE разделяет _E на _ и Е - mysql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если ничего не помогает, попробуйте почитать документацию.

    LIKE operator

    With LIKE you can use the following two wildcard characters in the pattern:

    • % matches any number of characters, even zero characters.
    • _ matches exactly one character.
    Ответ написан
    1 комментарий
  • Как посчитать общую длительность времени между строками определенной выборки в MySQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH cte AS ( SELECT *, 
                         LAG(`datetime`) OVER (PARTITION BY login ORDER BY `datetime`) lag_datetime, 
                         LAG(event) OVER (PARTITION BY login ORDER BY `datetime`) lag_event 
                  FROM history )
    SELECT login, SUM(TIMESTAMPDIFF(MINUTE, lag_datetime, `datetime`)) duration
    FROM cte
    WHERE (event, lag_event) = (2,1)
    GROUP BY login;

    https://dbfiddle.uk/?rdbms=mariadb_10.6&fiddle=398... (исходные данные подправлены).
    Ответ написан
    1 комментарий
  • Как использовать maxmind GeoLite2 на mysql 5.5, где нет inet6_aton?

    @Akina
    Сетевой и системный админ, SQL-программист.
    В результате надо получить таблицу, в которой будут только IPv4 адреса

    Не вижу проблемы. Импорт не использует inet6_aton. Соответственно после импорта можно просто удалить записи с IPv6-адресами. А затем ещё и изменить тип поля на VARBINARY(4).
    Ответ написан
  • Как группировать данные, если у них есть уникальные id?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Вы пытаетесь сделать откровенную глупость, выводя значение id в итоговом наборе.

    Вот есть некая группа, в ней все off_id одинаковы, но id различны. После группировки все эти записи будут сгруппированы в одну. А теперь, внимание, вопрос: ну и какое одно значение id из всех возможных сервер должен вернуть? не знаете? так ведь и сервер не знает... вот он и генерирует ошибку.

    Уберите id из выходного набора. Либо явно и чётко скажите серверу, какое именно значение из всех возможных в группе он должен вернуть. Наименьшее? требуйте MIN(id). Наибольшее? MAX(id). Хоть какое, любое? ANY_VALUE(id).
    Ответ написан
    Комментировать
  • Как выполнить SELECT с таким условием?

    @Akina
    Сетевой и системный админ, SQL-программист.
    aopil,
    а для более старых версий невозможно выполнить то, что я хочу?


    SELECT *
    FROM services
    JOIN (
        SELECT *,
               @row_number := CASE WHEN service_id = @service_id
                                   THEN @row_number + 1
                                   ELSE 1
                                   END rownumber,
               @service_id := service_id
        FROM orders
        CROSS JOIN (SELECT @service_id := 0, @row_number := 0) init_vars
        ORDER BY service_id, id DESC
        ) enumerated_orders USING (service_id)
    WHERE enumerated_orders.rownumber <= services.service_limit

    https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=1f2a95...
    Ответ написан
    1 комментарий
  • Как изменять значение в бд по времени?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Информация о том, что пользователь оплатил подписку заносится в бд (есть отдельная строка, в которой изначальное значение равно нулю, а при оплате меняется на 1).

    В комплекте с информацией о факте оплаты должна существовать и информация о дате-времени открытия доступа по подписке. Кстати, в этом случае сама информация о факте оплаты не нужна, достаточно просто самого факта наличия момента оплаты либо срока действия оплаченного доступа.

    значение сменилось на 1, а потом через месяц само сменилось на 0.

    Для этого у MySQL есть свой встроенный планировщик. Запускаем, создаём процедуру, которая выполняется, например, ежеминутно, и обнуляет поле доступа для всех записей, у которых разница между текущим штампом времени и штампом времени открытия доступа превышает срок доступа (хардкод, либо взятый из служебной таблицы или даже из обрабатываемой записи).

    MySQL 8.0 Reference Manual / Stored Objects / Usin...
    Ответ написан
    Комментировать
  • База данных MySql, как сделать переменную, с индивидуальным значением для всех аккаунтов?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Ну вообще-то под такие цели обычно создаётся специальная служебная таблица.
    Ответ написан
    2 комментария
  • Есть вариант сохранить в поле json (mysql) массив с нужным порядком?

    @Akina
    Сетевой и системный админ, SQL-программист.
    фишка в том, что в бд порядок меняется, условно скажем, после того, как вытащишь из бд и превратишь обратно в массив, он уже принимает вот такой вид

    Согласно описанию формата, порядок элементов внутри объекта не существует (вернее, не определён), и его поддержание не гарантируется. В отличие от массива.
    Так что если порядок важен, то каждая запись должна быть преобразована в отдельный объект, а все они - сложены в массив в нужном порядке, т.е. JSON должен выглядеть, например, так:
    '[{"a":1}, {"b":2}, {"c":3}]'

    Я его превращаю в json (json_encode), и кладу в бд.

    Покажите точно, как выглядит этот JSON.
    Покажите точный CREATE TABLE таблицы, в которую кладёте.
    Покажите, как точно выглядит в таблице положенное туда JSON значение.
    Покажите точно это же JSON значение после обратного извлечения.

    Да, всё это - для одного и того же JSON.
    Ответ написан
    Комментировать
  • Как заменить строку на цифры у оператора IN?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если передаваемый параметр - это CSV идентификаторов, то следует использовать
    SELECT *
    FROM `users`
    WHERE FIND_IN_SET(id, ?);


    Примечание 1. CSV не должен содержать никаких паразитных пробелов (а то любят всякие "украшатели" понатыкать пробелов после запятой).
    Примечание 2. Такой запрос - гарантированный фуллскан. Зато не будет инъекции.

    PS. В принципе этот CSV несложно довести до состояния JSON array (всего-то две скобки добавить) - тогда можно применить JSON_CONTAINS(), что может быть немного быстрее. А уж если переданный JSON распарсить на отдельные значения с помощью JSON_TABLE(), так ещё и от фуллскана избавимся (правда, версия сервера нужна достаточно свежая).
    Ответ написан
    2 комментария
  • Почему выдает ошибку 1442?

    @Akina
    Сетевой и системный админ, SQL-программист.
    CREATE DEFINER=root@localhost
    TRIGGER bi_trigger_in_employees
    BEFORE INSERT ON employees 
    FOR EACH ROW 
    SET NEW.entpr_name = COALESCE( NEW.entpr_name, 
                                   ( SELECT ap_name 
                                     FROM companies 
                                     WHERE id = NEW.entpr_id 
                                     LIMIT 1
                                    )
                                  ),
        NEW.employee_name = COALESCE( NEW.employee_name, 
                                      ( SELECT CONCAT_WS(' ',np_surname,np_name,np_patronymic) 
                                        FROM people 
                                        WHERE id = NEW.employee_id
                                        LIMIT 1
                                       )
                                     );

    1) Суть ошибки - именно та, что написана в сообщении. Нельзя UPDATE таблицы, на которой определён триггер (и другие DML - тоже нельзя).
    2) Изменять вставляемые значения надо до вставки, а не после. Потому BEFORE триггер.
    3) По-хорошему, нужен ещё аналогичный BEFORE UPDATE триггер.
    4) Все SET выполняются в одном операторе (см. https://dev.mysql.com/doc/refman/8.0/en/set-variab...). А триггер из одного оператора обходится и без BEGIN-END, и без DELIMITER.
    5) При скалярном присвоении из подзапроса ВСЕГДА добавляйте LIMIT 1. А по-хорошему ещё и ORDER BY. На показанный код ни то, ни другое не влияет - всё равно одна запись, ибо отбор по PK. Но вдруг структура поменяется, а про триггер забудете? Начнутся ошибки - оно надо?

    тогда да, ошибка на бесконечный цикл. Но тут почему?

    Как это ни странно, но в теле триггера неизвестно, на какое событие определён триггер.
    Ответ написан
    1 комментарий
  • Как разбить одну таблицу на две и правильно заполнить её данными из импорта?

    @Akina
    Сетевой и системный админ, SQL-программист.
    CREATE TABLE client ( clientid INT AUTO_INCREMENT PRIMARY KEY,
                          firstname VARCHAR(255),
                          lastname VARCHAR(255),
                          phone BIGINT,                           -- если исходный VARCHAR - поменять, 
                                                                  -- либо соотв. преобразование в INSERT
                          UNIQUE (firstname, lastname, phone) );  -- можно потом удалить
    
    INSERT INTO client (firstname, lastname, phone)
        SELECT DISTINCT firstname, lastname, phone
        FROM orders_old;
    
    CREATE TABLE order ( orderid INT AUTO_INCREMENT PRIMARY KEY,
                         ordernumber INT,
                         clientid INT,
                         FOREIGN KEY (clientid) REFERENCES client (clientid) );
    
    INSERT INTO order (ordernumber, clientid)
        SELECT orders_old.ordernumber, client.clientid
        FROM orders_old
        JOIN client USING (firstname, lastname, phone);

    NOT NULL - по вкусу.
    Ответ написан
    1 комментарий
  • Как задать поиск по совпадения в 2 и более слов?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Нужно каждое слово оборачивать в %?

    Нет. Вернее, этого недостаточно.
    Условие WHERE name LIKE '%сок%перс%', конечно, не пропустит указанные нежелательные записи - но и "Персиковый сок" тоже будет отброшен.

    Нужно проверять наличие каждого слова отдельно.

    SELECT *
    FROM table
    WHERE name LIKE '%сок%'
      AND name LIKE '%перс%';
    Ответ написан
    Комментировать
  • Как получить сумму стоимости товаров из массива json?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT test.id, SUM(jsontable.price) total_price
    FROM test
    CROSS JOIN JSON_TABLE(test.data,
                          '$.products[*]' COLUMNS (price INT PATH '$.price')) jsontable
    GROUP BY test.id

    fiddle
    Ответ написан
    Комментировать
  • Как выбрать нужные позиции в базе по датам?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT *
    FROM tablename
    WHERE data < CURRENT_DATE + INTERVAL 5 DAY
    -- AND data >= CURRENT_DATE
    Ответ написан
    Комментировать
  • Как добавить данные для каждого массива в трехмерным массиве PHP?

    @Akina
    Сетевой и системный админ, SQL-программист.
    $db->prepare("SELECT comments.id, ... , users.login
                       , :me AS me 
                  FROM `comments` ... ");
        $comments->execute([
        "id_post" => $dataAttr,
        "me" => $_SESSION["user"]["id_user"],
        ]);

    или типа того...
    Ответ написан
    1 комментарий
  • Как исправить ошибку Cannot add or update a child row: a foreign key constraint fails?

    @Akina
    Сетевой и системный админ, SQL-программист.
    высвечивает такую ошибку

    Ну тебе же вменяемо говорят, что не выполняется ограничение.

    Согласно ограничению то значение, которое ты вставляешь в поле dispatcher таблицы transportation в базе данных auto, уже должно существовать в поле id_dispatcher таблицы dispatcher той же базы.

    Так что следи, что идентификатор диспетчера, который ты присваиваешь полю, взят не с потолка.
    Ответ написан
    5 комментариев
  • Какие ограничения несёт в себе INSERT IGNORE для секционированных таблиц?

    @Akina
    Сетевой и системный админ, SQL-программист.
    INSERT INTO может привести к ошибке. По любой причине. При этом процесс вставки прерывается, а все уже внесённые в таблицы изменения - откатываются.

    INSERT IGNORE преобразует ошибку в предупреждение. При этом выполнение запроса продолжается, а запись, попытка вставки которой привела к ошибке, не вставляется.

    Замечание. Дублирование - не единственное событие, которое может вызвать ошибку. Может быть ещё куча причин (CHECK constraint, SIGNAL из триггера, нарушение внешнего ключа и т.п.). Причём далеко не все типы ошибок восстановимы и могут быть проигнорированы/преобразованы в предупреждение. Если ошибка невосстановимая (как правило, это системные или внешние ошибки) - запрос прерывается по ошибке и откатывается обычным образом.

    Замечание 2. Всё вышеописанное никак не пересекается с секционированием. За исключением случая, когда значение поля не соответствует диапазону ни для одной из секций. В этом случае IGNORE срабатывает штатно - ошибка преобразуется в предупреждение, проблемная запись не вставляется.

    Нужно игнорировать дублирующиеся данные. Буду делать INSERT IGNORE

    Кроме INSERT IGNORE INTO есть ещё два типа запросов, которые обрабатывают ошибку дублирования данных - это INSERT .. ON DUPLICATE KEY UPDATE и REPLACE INTO. Изучите их - возможно, какой-то из них лучше подходит для Вашей конкретной задачи. При этом REPLACE не поддерживает модификатор IGNORE и не может игнорировать другие ошибки.
    Ответ написан
    Комментировать
  • #1045 - Доступ закрыт для пользователя 'root'@'127.0.0.1', что делать?

    @Akina
    Сетевой и системный админ, SQL-программист.
    В OpenServer -> PHPMyAdmin я создал юзера root1

    Мало создать юзера, надо ещё дать ему необходимые для работы права. Хотя бы элементарно на чтение для той БД, которая указана как база по умолчанию.

    Вот параметры юзера

    Право USAGE - это синоним права “no privileges”. Т.е. свежесозданный юзер - абсолютно бесправен.

    Читайте и применяйте GRANT Statement. Особое внимание обратить на WITH GRANT OPTION.
    Ответ написан
    Комментировать
  • Как объединить два запроса в один?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT order.ID, 
           order_status.Name StatusName, 
           order.Name OrderName, 
           order.Phone
    FROM order
    JOIN order_status ON order.status = order_status.id

    Если соответствие в таблицах задано иначе - исправь ON clause.
    Ответ написан
    2 комментария
  • Как правильно удалить все строки с минимальным значением поля?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Удалить только самые старые (оставить все остальные)
    DELETE t1
    FROM table t1
    LEFT JOIN table t2 ON t1.dup_column = t2.dup_column
                      AND t1.time_column > t2.time_column
    WHERE t2.time_column IS NULL

    Оставить только самые новые (удалить все остальные)
    DELETE t1
    FROM table t1
    JOIN table t2 ON t1.dup_column = t2.dup_column
                 AND t1.time_column < t2.time_column


    Суть задачи удалить все дубли квартир приходящие с разных импортов, по умолчанию считаем что последний файл импорта актуальный

    Создай уникальный индекс по номеру квартиры (после чистки, само собой) и используй не INSERT INTO, а REPLACE INTO.
    Ответ написан