Задать вопрос
Ответы пользователя по тегу MySQL
  • Можно ли доверять коду ошибки Mysql?

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

    Error number: 1452; Symbol: ER_NO_REFERENCED_ROW_2; SQLSTATE: 23000

    Message: Cannot add or update a child row: a foreign key constraint fails (%s)

    InnoDB reports this error when you try to add a row but there is no parent row, and a foreign key constraint fails. Add the parent row first.

    Данная ошибка всегда порождается событием неудачной проверки ограничения ссылочной целостности. Так что можете смело доверять причине.

    Или перед вставкой нужно создать запрос на проверку существования такой записи в связующей таблице?

    А вот задайте себе вопрос - откуда возьмётся то самое значение user_id = 3, которое Вы собираетесь вставить? я не вижу иного способа получить данное значение кроме как сделать запрос в родительскую таблицу. А коли из неё вернётся нужное значение - то запись, из которой взято это значение, совершенно очевидно в таблице есть.
    Ответ написан
    5 комментариев
  • Как лучше реализовать динамические поля?

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

    Первый, уже указанный в комментарии от Ерлан Ибраев, EAV.

    Второй - сериализация динамических параметров. JSON, XML и т.п.

    В обоих вариантах по мере доработки параметры могут легко переноситься из динамического хранилища в постоянное. Также оба варианта допускают и множественные значения - в том числе в постоянном и временном хранилищах одновременно (что к тому же даёт потенцию одноступенчатой приоритезации).

    Явный недостаток обоих способов - использование унифицированного типа данных в таблице (как минимум строковый, а данные запросто могут потребовать ещё и binary collation) вне зависимости от реального типа сохраняемых данных. Ещё один явный недостаток - необходимость выноса контроля целостности на клиентский уровень.

    Что выбрать? а вот это уже зависит от того, что именно делается с данными.

    В любом случае - следует сразу отбросить идею динамической корректировки структуры хранения (изменения структуры таблиц, добавления таблиц) из клиентского кода.
    Ответ написан
  • Как правильно делать JOIN таблиц?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Есть ли разница джоинов этих двух строк, с точки зрения нагрузки на БД?

    Оба запроса - INNER JOIN. Если не используется STRAIGHT_JOIN, то сервер гарантированно построит для обоих запросов один и тот же план выполнения.

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

    @Akina
    Сетевой и системный админ, SQL-программист.
    Самое простое - сделать бэкап только структуры, без данных (mysqldump --no-data, https://dev.mysql.com/doc/refman/8.0/en/mysqldump....), удалить БД, восстановить. Само собой, не забыть забэкапить процедуры/триггеры/прочее.
    Ответ написан
    Комментировать
  • Как правильно указать значение SET?

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

    Для того. чтобы вставляемое значение не квотировалось, следует использовать плейсхолдер из 2 знаков вопроса:
    PreparedStatement ps = plugin.SQL.getConnection().prepareStatement("UPDATE PlayerBlocks SET ?? = ? WHERE UUID=?");

    Тогда первый передаваемый параметр - имя поля для обновления. 2 и 3 соответственно значения (новое и для условия отбора).
    Ответ написан
    4 комментария
  • Какой необходимо составить запрос mysql для генератора случайного поста по рейтингу?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Ну типа так.
    WITH cte AS (
        SELECT *, SUM(rating) OVER (ORDER BY id) cum_rating
        FROM table
    )
    SELECT
    FROM cte t1
    JOIN (SELECT RAND() * MAX(cum_rating) rnd_rating
          FROM cte) t2 ON t2.rnd_rating BETWEEN t1.cum_rating - t1.rating AND t1.cum_rating

    Реально, конечно, не BETWEEN, а два неравенства, по верхней границе - строгое.
    Ответ написан
  • Помощь с запросом MySQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT car_model.* 
    FROM car_model 
    JOIN car_mark ON car_model USING (id_car_mark)
    WHERE car_mark.name='AC'
    Ответ написан
    Комментировать
  • Почему mysql запрос не выводит запись где кол-во схождений 0?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Список требуемых id должен быть источником данных запроса, причём базовым. И при возможном отсутствии связанных записей связывание должно быть внешнее.
    SELECT service.id AS service_id, COUNT(subs.id) AS c
    FROM ( SELECT 13 id UNION 
           SELECT 74    UNION
           SELECT 71    UNION
           SELECT 72 ) AS service
    LEFT JOIN Subscriptions subs ON subs.service_id = service.id AND subs.msisdn=992777757031
    GROUP BY service.id
    ORDER BY c DESC;
    Ответ написан
  • Как убрать лишние значения при JOIN по неуникальным полям?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH 
    cte1 AS ( SELECT id, name, ROW_NUMBER() OVER (ORDER BY name) rn
              FROM t1 ),
    cte2 AS ( SELECT id, name, ROW_NUMBER() OVER (ORDER BY name) rn
              FROM t2 )
    SELECT cte1.id id1, cte1.name name1, cte2.id id2, cte2.name name2
    FROM cte1
    JOIN cte2 USING (rn, id);


    https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=b5a064...

    Хотя, конечно, бред рафинированный. С точки зрения логики.
    Ответ написан
  • Как правильно указать WHERE если делаем LEFT JOIN?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Порядок кляуз в запросе чётко определён в документации, и никаких изменений и перестановок не предполагает (исключение - кляуза INTO при помещении результата в переменную, для которой описано 3 разных местоположения).
    SELECT u.*, t.type_name, t.description 
    FROM users AS u 
    LEFT JOIN type_user AS tu ON tu.id_user = u.id 
    LEFT JOIN types AS t ON tu.id_type = t.id
    WHERE u.id = 1;
    Ответ написан
    Комментировать
  • Можно ли и как составить запрос в БД, чтобы получить статистические данные?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH RECURSIVE
    cte1 AS ( SELECT MIN(DATE(create_date)) mindate, MAX(DATE(create_date)) maxdate
              FROM shops
              UNION ALL
              SELECT MIN(DATE(create_date)) mindate, MAX(DATE(create_date)) maxdate
              FROM users ),
    cte2 AS ( SELECT MIN(mindate) mindate, MAX(maxdate) maxdate
              FROM cte1 ),
    dates AS ( SELECT mindate thedate, maxdate
               FROM cte2
               UNION ALL
               SELECT thedate + INTERVAL 1 DAY, maxdate
               FROM dates
               WHERE thedate < maxdate ),
    shopstat AS ( SELECT DATE(create_date) thedate, COUNT(*) cnt
                  FROM shops
                  GROUP BY thedate ),
    userstat AS ( SELECT DATE(create_date) thedate, COUNT(*) cnt
                  FROM users
                  GROUP BY thedate )
    SELECT thedate `date`, 
           COALESCE(shopstat.cnt, 0) shops, 
           COALESCE(userstat.cnt, 0) users
    FROM dates
    LEFT JOIN shopstat USING (thedate)
    LEFT JOIN userstat USING (thedate)


    Если нужны данные за определённый период - убрать cte1 и cte2, использовать границы диапазона в dates (поле maxdate - не нужно, убрать), добавить соотв. WHERE в остальные CTE.
    Ответ написан
    Комментировать
  • Как использовать CONVERT_TZ и AS?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Алиас выходного поля нельзя использовать во WHERE.

    Правильно - использовать копию вычисляющего значения выражения:
    SELECT event, 
           CONVERT_TZ(time, '+00:00', '-04:00') AS time1 
    FROM events 
    WHERE CONVERT_TZ(time, '+00:00', '-04:00') between '2021-06-24 00:00:00' AND '2021-06-24 23:59:59' 
      AND lang = 'ru'

    Расширение MySQL также допускает использовать алиас выходного поля в HAVING (при условии что в выражении не используются оконные функции):
    SELECT event, 
           CONVERT_TZ(time, '+00:00', '-04:00') AS time1 
    FROM events 
    WHERE lang = 'ru'
    HAVING time1 between '2021-06-24 00:00:00' AND '2021-06-24 23:59:59'
    Ответ написан
    Комментировать
  • Как выводить записи не раннее получаса и не позднее часа в sql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WHERE created_at BETWEEN CURRENT_TIMESTAMP - INTERVAL 1 HOUR
                         AND CURRENT_TIMESTAMP - INTERVAL 30 MINUTE
    Ответ написан
    Комментировать
  • Как вычесть у одного пользователя число и добавить его другому?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Лучше делать всё в одном запросе:
    UPDATE users u1
    CROSS JOIN users u2
    SET u1.amount = u1.amount - $summa,
        u2.amount = u2.amount + $summa
    WHERE u1.id = $client
      AND u2.id = $shop;


    Во-первых, один запрос - проще. Пусть даже сам запрос и сложнее.

    Во-вторых, если, например, в структуре таблицы имеется ограничение CHECK (amount >= 0), а сумма такова, что у клиента баланс уйдёт в минус - в таком случае ни одна из записей не будет изменена.
    Ответ написан
    Комментировать
  • Что не так с моим запросом?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT main.id,
           ( SELECT COUNT(*) 
             FROM news 
             WHERE main.id = news.main_id ) news,
           ( SELECT COUNT(*) 
             FROM articles
             WHERE main.id = articles.main_id ) articles
    FROM main
    ORDER BY news DESC;


    Предполагается, что main(id) есть уникальное поле (скорее всего первичный ключ).
    Ответ написан
    2 комментария
  • Как можно добавить данные в несколько таблиц через один insert into?

    @Akina
    Сетевой и системный админ, SQL-программист.
    MySQL не поддерживает многотабличный INSERT.

    Варианты:
    1. Хранимая процедура
    2. Триггер (но нужно решать проблему с передачей параметров для остальных таблиц)
    Ответ написан
    9 комментариев
  • Как исправить Fatal error in defaults handling. Program aborted?

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

    Чудес не бывает. Если сервер считает, что файл кривой, то он прав. А ты чего-то не замечаешь.

    пробовал ставить кодировку ANSI

    Должен быть чистый ASCII.
    Ответ написан
    Комментировать
  • Почему value="" записывает пустоту, а не NULL?

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

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

    SELECT 500 queue, operator, os.avg_os, ss.avg_ss
    FROM ( SELECT operator,AVG(valuation) avg_os
           FROM oper_survey 
           WHERE queue = '500' AND `date` BETWEEN '2021-06-01' AND '2021-06-16' 
           GROUP BY operator ) os
    JOIN ( SELECT operator, AVG(valuation) avg_ss
           FROM service_survey 
           WHERE queue = '500' AND `date` BETWEEN '2021-06-01' AND '2021-06-16' 
           GROUP BY operator ) ss USING (operator)


    Более сложный вариант - какой-то operator отсутствует в одной из таблиц. Тогда надо собрать список из обеих таблиц, и к нему привязывать считающие подзапросы.

    SELECT 500 queue, operator, COALESCE(os.avg_os, 0) avg_os, COALESCE(ss.avg_ss, 0) avg_ss
    FROM ( SELECT operator FROM oper_survey WHERE queue = '500'
           UNION 
           SELECT operator FROM service_survey WHERE queue = '500' ) op
    LEFT JOIN ( SELECT operator,AVG(valuation) avg_os
                FROM oper_survey 
                WHERE queue = '500' AND `date` BETWEEN '2021-06-01' AND '2021-06-16' 
                GROUP BY operator ) os USING (operator)
    LEFT JOIN ( SELECT operator, AVG(valuation) avg_ss
                FROM service_survey 
                WHERE queue = '500' AND `date` BETWEEN '2021-06-01' AND '2021-06-16' 
                GROUP BY operator ) ss USING (operator)
    Ответ написан
    Комментировать
  • Как выполнить подзапрос в SQL (SELECT с передачей параметра из основного запроса?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT users.name AS username,
           count(orders.id) AS orders_count 
    FROM users
    JOIN orders ON orders.user_id=users.id
    GROUP BY users.name

    Если нужно вывести и пользователей, у которых нет заказов, с нулевым количеством, то использовать LEFT JOIN.

    PS. Запрос из текста вопроса тоже корректен и должен дать правильный результат. Причём с 50% вероятностью он будет преобразован в мой (точнее, оба дадут один и тот же план выполнения). Остальные 50% - на то, что он будет выполнен итерационно (и тогда скорее всего просто будет выполняться дольше).
    Ответ написан
    2 комментария