Задать вопрос
Ответы пользователя по тегу MySQL
  • Как сделать ORDER BY совместно с GROUP BY в MySQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT t1.*
    FROM table AS t1
    NATURAL JOIN (
        SELECT user_id, MAX(timestamp) AS timestamp
        FROM table AS t2
        GROUP BY 1
    ) AS t3


    Если вдруг для юзера время может иметь дубликаты - будут выведены все соотв. записи.
    Ответ написан
    Комментировать
  • MSSQL and mysql в чем отличие?

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

    Не надо путать причину и следствие. Причина - это что ты ни хрена не понимаешь. А следствие - оно тебе кажется убожеством.
    offtop
    В скобках отмечу, что если ты не только ни хрена не понимаешь, но и жалуешься на это, и считаешь это достаточным обоснованием того, чтобы назвать убожеством - то ты и не хочешь понимать, и не пытаешься понять. В смысле не пытаешься по-настоящему, прочтение пары страниц из мануала под этот термин не проходит.


    отличаются ли запросы sql MSSQL от Mysql

    Да. Точнее, самые простейшие базовые запросы могут выглядеть одинаково. Но не более, чуть только хоть какая-то сложность, и одинаковость заканчивается. Синтаксис различается, и весьма сильно. А кое-где даже подходы к решению задачи различаются, и код с одной СУБД на другую не адаптируется совсем - только полное переписывание.

    возможно ли сменить БД без нарушения функциональности софта.

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

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT ..
    FROM ..
    GROUP BY (unixtime_column MOD 60*60*24) DIV 60*60
    Ответ написан
    8 комментариев
  • Как связать таблицу с собой?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT t1.id, COALESCE(t1.f2, t2.f2) f2, t1.f3       
    FROM test t1
    LEFT JOIN test t2 ON t2.id = t1.f1

    Если пустые ячейки - не NULL, а пустая строка, то COALESCE(NULLIF(t1.f2, ''), t2.f2).
    Ответ написан
    Комментировать
  • Mysql, как выполнять события(events) только при условии?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если просто переписать в соответствии с правильным синтаксисом, и при этом избавиться от ненужного IF, то
    CREATE DEFINER=`sql_test`@`%` EVENT `Маркировка` 
    ON SCHEDULE 
        EVERY 1 HOUR 
        STARTS '2022-05-29 23:15:23' 
    -- ON COMPLETION NOT PRESERVE   -- не имеет смысла для периодической задачи
    -- ENABLE                       -- по умолчанию эвент включен при создании
    DO
    UPDATE `tasks` 
    SET `status` = 4  
    WHERE `status` = 3
      AND EXISTS ( SELECT NULL  
                   FROM `config` 
                   WHERE `name` = 'profile_deleting'
                     AND `value` = 'allowed' );

    Однако логика какая-то странная - обновляются все записи, и при этом проверяется наличие абы какой записи. Хотя разум требует наличия зависимости между обновляемой и проверяемой записями.

    ======

    Впрочем, никто не запрещает сохранить исходный вид:
    CREATE DEFINER=`sql_test`@`%` EVENT `Маркировка` 
    ON SCHEDULE 
        EVERY 1 HOUR 
        STARTS '2022-05-29 23:15:23' 
    -- ON COMPLETION NOT PRESERVE 
    -- ENABLE 
    DO
    BEGIN
      IF (SELECT `value` FROM `config` WHERE `name` = 'profile_deleting') = 'allowed' THEN 
        UPDATE `tasks` SET `status` = 4  WHERE `status` = 3;
      END IF;
    END;

    Но:
    1. при создании такой процедуры придётся переопределять DELIMITER
    2. если подзапрос вернёт более одной записи - это приведёт к ошибке

    Проблему с возвращающим более одной записи подзапросом можно поправить следующим изменением:
    IF 'allowed' IN (SELECT `value` FROM `config` WHERE `name` = 'profile_deleting') THEN
    Ответ написан
    3 комментария
  • Как найти строку по значению и изменить соседнее значение?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WebDiez
    Затупил.. Нашел вариант..

    Пока надо обновлять для строго одной записи - сойдёт. А вообще
    UPDATE request 
    JOIN ( SELECT MAX(id) id 
           FROM request 
           WHERE user_id IN ( '97'  /* список */ )
         ) subquery USING ( id )
    SET request.message = 'text';
    Ответ написан
    Комментировать
  • Как сделать массовое обновление записей в mysql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH `cte` AS (
        SELECT 123 `id`, 1 `stat` UNION ALL
        SELECT 321     , 2        UNION ALL
     -- ...
        SELECT 456     , 8        UNION ALL
        SELECT 789     , 9
    )
    UPDATE `data`
    JOIN   `cte` USING ( `id` )
    SET `data`.`stat` = `cte`.`stat`;
    Ответ написан
    6 комментариев
  • Как сделать чтобы строка не вставлялась в БД, если не соблюдается формат поля?

    @Akina
    Сетевой и системный админ, SQL-программист.
    ALTER TABLE customer
    ADD CONSTRAINT CHECK(phone REGEXP '^[0-9]{3}-[0-9]{2}-[0-9]{3}$');

    https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=71012d...
    Ответ написан
    Комментировать
  • Нужно использовать триггеры или нет??

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

    Как я понимаю, мысль твоя бредёт вот в каком направлении: мы выполняем INSERT в основную таблицу, а триггер AFTER INSERT, имеющий доступ к сгенерированному значению автоинкрементного ключа именно свежесозданной записи, создаёт записи в связанных таблицах, используя именно это значение.

    Так вот именно эта мысль - она некорректная. Причём по совершенно элементарной причине. Данные для вставки в связанных таблицах (не поля связи - других полей) триггер тоже должен откуда-то взять. А вот корректно передать их достаточно непросто. Их нельзя вставить в блок данных основной записи - там просто места для этого нет, сервер перед выполнением INSERT проверяет входные данные на соответствие количества значений количеству переданных данных, соответствие типов, непревышение размеров и пр. Значит, данные придётся передавать за пределами запроса. Да, тут есть варианты, типа определённых пользователем переменных, временных таблиц и протчая - но всё это ненадёжно, сложно и совершенно несопровождаемо. Следует ещё учесть то, что триггеры - это конструкция неотключаемая. Либо она выполняется при абсолютно любом INSERT, и тогда есть определённые проблемы (триггер, предназначенный для работы при INSERT .. VALUES с единственным блоком данных, вряд ли корректно обработает вставку нескольких блоков данных, INSERT .. SELECT или LOAD DATA), либо для выполнения запросов на массовое добавление триггер надо удалять и потом пересоздавать - а если это происходит в конкурентной среде?

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

    при регистрации пользователя, я получаю lastInserdId() и добавляю статичные данные для этого пользователя в различные таблицы

    Ненадёжно. Если между вставкой в основную таблицу и получением LAST_INSERT_ID() соединение будет разорвано и затем автоматически восстановлено, то полученное значение будет некорректным (вернее, получите NULL). А свежесозданная запись благополучно "повиснет в воздухе".
    Чисто теоретически, базовая таблица пользователей обязана обеспечивать уникальность записи даже без учёта синтетического первичного ключа (например, поле логина явно должно быть уникальным). А коли так, и с учётом того, что все значения для свежевставленной записи нам известны, можно использовать INSERT INTO slave SELECT 'literal', main.id FROM main WHERE uniquecolumn = 'new value'.

    PS. Не знаю, почему при обучении вставке данных все начинают с INSERT .. VALUES - как по мне, глубоко порочная практика. Сначала надо изучить и досконально освоить INSERT .. SELECT, и только потом упоминать про INSERT .. VALUES как более простой конструкции, применимой в частных случаях.
    Ответ написан
    1 комментарий
  • Возможно ли узнать последнюю дату изменения таблицы mysql?

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

    Решение через INFORMATION_SCHEMA.TABLES.UPDATE_TIME - это плюс-минус лапоть. Для большинства движков - это время обновления файла таблицы в файловой системе, а вовсе даже не время выполнения последней записи по результатам выполнения последнего запроса на изменение данных (да-да, для долгого запроса это будет SYSDATE() последней изменённой записи, а не CURRENT_TIMESTAMP). Да и на дефолтном InnoDB не всё слава богу - кэширование запросто может добавить несколько секунд, а при отключенном file_per_table и на партиционированных таблицах так и вовсе не работает.
    Ответ написан
    1 комментарий
  • Как отсортировать запрос с UNION?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если отформатировать запрос, то он выглядит так:
    SELECT * FROM `rsi` WHERE `tf`='4h'                         UNION 
    SELECT * FROM `rsi` WHERE `tf`='15m'                        UNION 
    SELECT * FROM `rsi` WHERE `tf`='4h'                         UNION 
    SELECT * FROM `rsi` WHERE `situation`='perek' AND `tf`='1d' UNION 
    SELECT * FROM `rsi`                                         UNION 
    
    SELECT * FROM `levels` WHERE `situation`='support' AND `tf`='4h' UNION 
    SELECT * FROM `levels` WHERE `tf`='1h' 
    
    ORDER BY `time` DESC LIMIT 0,20

    Сразу видно, что первые 4 подзапроса можно смело удалить.
    А потом надо смотреть на структуру таблицы rsi, ибо именно из неё будут взяты имена полей объединённого набора записей. Судя по ошибке, там просто нет поля time.
    Ответ написан
    1 комментарий
  • Как выбрать нужные записи из бд?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT *
    FROM table
    ORDER BY user_id = @user_id DESC, id DESC LIMIT 1

    Если заданный @user_id есть - вернётся соотв. запись. Если таких записей несколько - вернётся запись из них с максимальным id. Иначе вернётся просто запись с макс. id.

    Если же под "Если есть user_id вернуть запись с user_id" разумеется "ну хоть какой-то, лишь бы не NULL", то
    SELECT *
    FROM table
    ORDER BY user_id IS NULL, id DESC LIMIT 1
    Ответ написан
    Комментировать
  • Как сравнить такие столбцы?

    @Akina
    Сетевой и системный админ, SQL-программист.
    table1.id = SUBSTRING_INDEX(table2.id, '=', -1)
    Ответ написан
    Комментировать
  • Какую длину может содержать условие выборки по ID?

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

    Есть. Ограничение на размер пакета.

    Кроме того, если список ID предварительно скинуть в temporary table primary key (id) engine=memory, то запрос при большом (~ более 10к значений) списке даже с учётом времени на создание и наполнение временной таблицы выполняется быстрее.
    Ответ написан
    Комментировать
  • Как синхронизировать столбцы в SQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если связь между значениями - статическая, жёсткая и никогда не изменяемая, то используйте вычисляемое поле (generated column). Если значение поля, от которого зависит другое поле - числовое от единицы и далее, можно обойтись одним полем типа ENUM.

    Если же связь более сложная и/или может меняться со временем, то гораздо разумнее не заполнять второе поле в зависимости от первого, а использовать его значение как ссылку (foreign key) в словарную таблицу.

    Крайний случай - использование BEFORE INSERT/UPDATE триггеров.
    Ответ написан
    Комментировать
  • Как правильно будет сделать JOIN?

    @Akina
    Сетевой и системный админ, SQL-программист.
    andry33822, огорчу. Описанная мной в комментарии к вопросу процедура требует ВСТАВКИ записи в таблицу users и ОБНОВЛЕНИЯ существующей записи в таблице users_apikey. То есть INSERT в одну таблицу + UPDATE другой таблицы.

    В один запрос это никаким образом не укладывается. Но задачу можно решить. Триггером.

    CREATE TRIGGER tr_assign_apikey_to_user
    AFTER INSERT 
    ON users
    FOR EACH ROW
    UPDATE users_apikey SET username = NEW.username WHERE username = '' LIMIT 1;


    DEMO fiddle

    Правда, триггер простейший, и ничего не проверяет. По-хорошему надо как минимум проверить, что свободный apikey - есть, и если нет - то сгенерировать ошибку добавления юзера. Ну и не исключаю дополнительных условий - например, мне лично запись в apikey, не имеющая вменяемого значения в поле namekey, как-то не нравится.
    Ответ написан
    Комментировать
  • Что происходит при повторном запуске команды MySQL source?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Что происходит при повторном запуске? Проверяется наличие уже импортированных записей, они пропускаются и импортируется отсутствующие?

    Никаких проверок. Запуск с самого начала.

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

    В общем, как обычно. Если возникла ошибка, надо не пытаться запустить повторно, типа авось пролезет (почти наверняка - не пролезет), а разбираться, почему возникла ошибка, и устранять причину.
    Ответ написан
    Комментировать
  • Как восстановить базу sql из файлов /var/lib/mysql/* на другом сервере mysql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    При попытки создать mysqldump база выдаёт ошибку:
    Illegal mix of collations (utf8_unicode_ci,COERCIBLE) and (utf8_general_ci,COERCIBLE) for operation 'locate'

    Скорректируйте @@collation_connection.

    Задача сделать копию битой БД mysql ... как из файлов "холодного резерва" создать sql-файл или как эту базу развернуть на другом сервере mysql?

    А смысл? если подключить файлы данных в новом местоположении, ошибки никуда не денутся.

    А так - создать таблицы в новом местоположении. Структура должна совпадать с точностью до запятых, и версия сервера тоже. Самое разумное - сделать бэкап чисто структуры, без данных, и развернуть. А потом DISCARD/IMPORT TABLESPACE, либо замена файлов при остановленном сервисе и последующий запуск с лечением и перезаписью метаданных и статистики.
    Ответ написан
  • Как правильно импортировать много данных из json в mysql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Artikul2,
    MySQL 8.0.28-0ubuntu0.20.04.3


    Не делай ничего с этим JSON. Отдай его как есть на MySQL - у него парсинг получится лучше...
    INSERT INTO test (name, position, city, postcode, entered_at, income)
    SELECT data ->> '$[0]' name,
           data ->> '$[1]' position,
           data ->> '$[2]' city,
           data ->> '$[3]' postcode,
           STR_TO_DATE(data ->> '$[4]', '%Y\/%m\/%d') entered_at,
           REPLACE(SUBSTRING(data ->> '$[5]' FROM 2), ',', '') income
    FROM JSON_TABLE(@data,
                    '$.data[*]' COLUMNS (data JSON PATH '$')) jsontable


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

    Если надо отсеивать дубликаты - создать соотв. уникальный индекс, и использовать INSERT ODKU, REPLACE INTO либо INSERT IGNORE.
    Ответ написан
  • Как сменить пользователя в MySQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Как сменить пользователя в MySQL?

    В текущем соединении - никак. Только (закрыть это и) создать новое соединение, с использованием другой учётной записи.
    Ответ написан