Ответы пользователя по тегу MySQL
  • Как составить запрос выборки баллов?

    @Akina
    Сетевой и системный админ, SQL-программист.

    Мне нужно найти запись на который у пользователя где у пользователя 1 накопится допустим 30 баллов, это запись id=5.


    WITH cte AS (
        SELECT *, SUM(point) OVER (ORDER BY point_lifetime) cum_sum
        FROM tablename
        WHERE user_id = 1 --   у пользователя 1 
        )
    SELECT *
    FROM cte
    WHERE cum_sum >= 30   --   накопится 30 баллов
    ORDER BY point_lifetime LIMIT 1;


    PS. Поскольку значения в point_lifetime неуникальны, то однозначного решения может и не быть. Во всяком случае до тех пор, пока не будет точно определён порядок записей при равенстве значений этого поля.
    Ответ написан
    Комментировать
  • Как сделать верную группировку в Union?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT id, MIN(type) type
    FROM t1
    WHERE type IN (1, 2)
    GROUP BY id
    Ответ написан
    4 комментария
  • Стоит ли переноносить таблицу из базы mysql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    MySQL глубоко параллельно, в какой БД лежит таблица (надеюсь, innodb_file_per_table включен?). Посему вынос таблицы в отдельную БД не окажет вообще никакого влияния на работу системы. Разве что незначительно изменится процент кэширования - но скорее всего это даже детектировать не выйдет.

    Если это высоконагруженная таблица с большим потоком запросов на изменение, то имеет смысл для неё создать отдельный tablespace и вынести его на быстрый (SSD) раздел. Плюс согласен с Everything_is_bad - партиционирование (в зависимости от вида основного шаблона запросов в потоке - по юзеру или по дате) может способствовать оптимизации работы с таблицей.
    Ответ написан
    Комментировать
  • Как исправить ошибку связанную с FULL JOIN?

    @Akina
    Сетевой и системный админ, SQL-программист.
    MySQL в принципе не знает о существовании FULL JOIN. И это как раз тот редчайший случай, когда сообщение об ошибке не соответствует проблеме.

    Проблема решается эмуляцией. Есть как минимум два варианта:

    SELECT * FROM table1 LEFT JOIN table2 USING (column)
    UNOIN ALL
    SELECT * FROM table1 RIGHT JOIN table2 USING (column) WHERE table1.column IS NULL

    SELECT *
    FROM (
        SELECT DISTINCT column FROM table1
        UNION ALL
        SELECT DISTINCT column FROM table2
        ) AS table0
    LEFT JOIN table1 USING (column)
    LEFT JOIN table2 USING (column)

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

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

    В MySQL нет "ячеек" - это не Excel. Есть записи, есть поля, есть поле отдельной записи.

    Если в ячейку типа TEXT не влазят данные, MySQL автоматически увеличит её до необходимого размера или выдаст исключение?

    Если размер данных превышает размер для типа данных поля - будет выдана ошибка или предупреждение "data too long". Что именно будет выдано - зависит от того, какой запрос, и от текущих настроек сессии.

    Как сделать "резиновую" ячейку в таблице?

    Никак. Но если нужно помещать в таблицу данные, которые не лезут в LONGTEXT (а это ни много ни мало 4 гигабайта!) - то Вы явно выбрали инструмент не по задаче. Храните такое в файловой системе.
    Ответ написан
  • Некоторые бинарные строки не определяются по оператору LIKE, проблема не дебажится, в чём может быть причина?

    @Akina
    Сетевой и системный админ, SQL-программист.
    LIKE в принципе не пригоден для указанной операции. Это чисто текстовый оператор. В частности, он безусловно применяет к обоим операндам регистронезависимый collation - в этих условиях сравнение БИНАРНЫХ строк способно давать весьма неожиданные эффекты.

    Если надо работать именно с бинарными строками - всё плохо. В MySQL нет нормальных функций для работы с ними.

    Для решения задачи рекомендую преобразовать бинарную строку в шестнадцатеричное представление, укоротить до 40-символьного (что соответствует 20-байтовому бинарному значению), преобразовать обратно, и сравнить.

    WHERE CONV(LEFT(HEX('$entered_hash'), 40), 16, 10) = correct_hash


    К тому же такое условие SARGable.

    PS. В выражении
    WHERE '{value1}' = '{value2}' OR '{value1}' LIKE '{value2}%'
    первое условие заведомо лишнее (ведь если оно выполняется, то и второе тоже выполняется).
    Ответ написан
    7 комментариев
  • MySQL PDO, Почему все значения при выборке типа string?

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

    То есть какие-то дополнительные преобразования, изменяющие тип данных, выполняет PHP уже после того, как он получил ответ от MySQL. Или не PHP, а коннектор, который PHP использует для доступа к MySQL. Но в любом случае это происходит уже на стороне клиента.

    Предположу, что эмуляция - процесс двусторонний. То есть не только на пути "туда", но и на обратном пути. Что при дополнительной обработке, которую требует настройка PDO::ATTR_EMULATE_PREPARES => true, корёжит тип данных.

    На всякий случай проверьте, не вызывает ли изменение этого флага корректировки других флагов. В частности, PDO::ATTR_STRINGIFY_FETCHES.
    Ответ написан
  • Как составить ассоциацию squelize один к одному?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Как составить ассоциацию squelize один к одному?

    В MySQL связи "один к одному" не существует в принципе. Точнее, такая связь нереализуема на изменяемом наборе данных. Неважно, напрямую или через какой-либо ORM, включая и Sequelize.

    Возможна только реализация связи "один к (ноль либо один)".
    Ответ написан
    Комментировать
  • Как сделать дополнительную выборку записей?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH 
    cte AS (
        SELECT * , 
               ROW_NUMBER() OVER (ORDER BY `date` DESC, id DESC) rn, 
               DENSE_RANK() OVER (ORDER BY `date` DESC, id DESC) dr
        FROM `list` 
        WHERE user='1' 
        )
    SELECT *
    FROM cte
    WHERE dr <= (
        SELECT dr
        FROM cte
        WHERE rn = 25
        )

    Версия сервера: 5.6.51 - MySQL Community Server (GPL)

    SELECT *
    FROM `list`
    WHERE user='1' 
      AND `date` >= (
        SELECT `date`
        FROM 'list'
        WHERE user='1' 
        ORDER BY `date` DESC, id DESC LIMIT 24, 1
    )
    Ответ написан
    4 комментария
  • JSON_REMOVE меняет порядок ключей?

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

    Бред сивой кобылы. Согласно стандарту, свойства в объекте не имеют такой характеристики как относительный порядок. Они являются ключами коллекции - поэтому, кстати, ещё и не могут дублироваться.

    Кстати, сразу понятно, что поле имеет текстовый тип данных, а не JSON. Иначе бы эффект изменения порядка ключей в текстовом представлении JSON давно бы вылез.

    Если такой порядок важен - следует использовать массив, а не объект.
    Ответ написан
  • Как пофиксить ошибку Incorrect TIMESTAMP value?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если значение поля с типом TIMESTAMP некорректно (а пустая строка - это некорректное значение) - надо заменить его на корректное.
    • Если поле NULLable - то например на NULL.
    • Если настройки допускают нулевую дату - то на `0000-00-00 00:00:00`.
    • Иначе - на некое предопределённое значение. В зависимости от смысла поля - либо в далёком прошлом, либо в столь же далёком будущем.
    Ответ написан
    Комментировать
  • Как сохранить порядок номеров в запросе?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT * 
    FROM table 
    WHERE id IN (7, 8, 5, 4, 1)
    ORDER BY FIND_IN_SET(id, '7,8,5,4,1');
    Ответ написан
    Комментировать
  • Как объединить запросы?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Два LEFT JOIN, условие связывания - по id и определённому значению типа.
    Ответ написан
    Комментировать
  • Можно ли сделать такое отношение таблиц?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Связь типа M:N между продуктом и материалом должна трактоваться как самостоятельная сущность. И, как любая другая сущность, она может иметь свои собственные атрибуты.

    можно ли в промежуточную таблицу добавлять поле amount или это считается недопустимым?

    Количество в данном случае - атрибут именно связи, а не продукта и не материала. Посему поле количества в связывающей таблице не только допустимо, но и единственно правильно. При условии, что на комбинацию полей (product_id, material_id) наложено требование уникальности. Иначе должна существовать ещё одна таблица, которая ссылается на связующую таблицу и содержит поле количества.
    Ответ написан
    Комментировать
  • Как выбрать последнюю запись с group by?

    @Akina
    Сетевой и системный админ, SQL-программист.
    А решение было близко... раз нужны данные с разных уровней группировки, то либо вертеть подзапросы/CTE, либо использовать оконные функции. Как по мне, второе проще.
    SELECT DISTINCT
           product_id,
           size,
           SUM(orders) OVER (PARTITION BY product_id, warehouse_id, size) AS orders,
           FIRST_VALUE(stocks) OVER (PARTITION BY product_id, warehouse_id, size 
                                     ORDER BY `date` DESC) AS stocks,
           warehouse_id
    FROM stats
    WHERE DATE(`date`) >= '2023-09-01' 
      AND DATE(`date`) <= '2023-09-04';

    fiddle
    Ответ написан
  • Как построить дерево одним запросом c сортировкой по родителю?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Как-то так:
    WITH RECURSIVE
    cte AS (
        SELECT *, LPAD(id, 10, '0') path
        FROM comments
        WHERE parent_id = 0
      UNION ALL
        SELECT comments.*, CONCAT(cte.path, LPAD(comments.id, 10, '0'))
        FROM comments
        JOIN cte ON cte.id = comments.parent_id
    )
    SELECT id, parent_id, content
    FROM cte
    ORDER BY path;

    Откорректировать длину в зависимости от типа данных.
    Ответ написан
    Комментировать
  • Как работает кластер galera?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Данные поступают на один из серверов кластера. Оттуда они распространяются/реплицируются на остальные серверы кластера. Очевидно, что процесс передачи на другие серверы - не мгновенный, и требует некоторого времени. И столь же очевидно, что если после получения новых данных, но до передачи их в другие серверы кластера исходный сервер сдох, то этих данных не будет на оставшихся серверах, и, как Вы правильно заметили, запросы будут выполняться с устаревшими данными.

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

    @Akina
    Сетевой и системный админ, SQL-программист.
    При добавлении набора данных в связанные таблицы (а по большому счёту - вообще всегда) следует забыть о существовании INSERT .. VALUES и пользоваться исключительно INSERT .. SELECT. Первый запрос вставляет запись в основную таблицу, второй вставляет в зависимую, получая необходимое для связывания значение из основной по известным критериям отбора (по только что вставленным значениям, либо, в случае MySQL, из LAST_INSERT_ID).
    Ответ написан
    Комментировать
  • Почему выдает ошибку создание триггера?

    @Akina
    Сетевой и системный админ, SQL-программист.
    CREATE TRIGGER fff
    BEFORE INSERT ON stats
    FOR EACH ROW
       SET NEW.column11 = (NEW.column1 + NEW.column2 + NEW.column3 + NEW.column4 + NEW.column5 + NEW.column6 + NEW.column7 + NEW.column8 + NEW.column9 + NEW.column10) / 10;

    или
    DELIMITER ;;
    
    CREATE TRIGGER fff
    BEFORE INSERT ON stats
    FOR EACH ROW 
    BEGIN
       SET NEW.column11 = (NEW.column1 + NEW.column2 + NEW.column3 + NEW.column4 + NEW.column5 + NEW.column6 + NEW.column7 + NEW.column8 + NEW.column9 + NEW.column10) / 10;
    END;
    ;;
    
    DELIMITER ;
    Ответ написан
    Комментировать
  • Как установить максимальное количество строк в таблице?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Демонстрация метода замены вставки на обновление: fiddle.
    Ответ написан
    Комментировать