Ответы пользователя по тегу MySQL
  • Можно ли сделать составной уникальный ключ "в обе стороны" (напр. 3 и 15 == 15 и 3)?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Задача решается созданием вычисляемого поля. Один из вариантов:
    CREATE TABLE test (
        id_1 INT,
        id_2 INT,
        ids VARCHAR(255) AS (CONCAT(LEAST(id_1, id_2), ' ', GREATEST(id_1, id_2))) STORED,
        PRIMARY KEY(ids),
        CHECK (id_1 <> id_2)
    );

    DEMO

    В принципе, можно и триггером... но менее надёжно.
    Ответ написан
    8 комментариев
  • Как вставить в строки значение с увеличением числа в БД?

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

    Решение 1. Более простое, но может давать дубликаты в конкурентной среде.
    CREATE TRIGGER tr_name
    BEFORE INSERT
    ON articles
    FOR EACH ROW
    SET NEW.image = CONCAT('catalog/blog-image/', COALESCE((SELECT 1 + MAX(SUBSTRING_INDEX(image, '/', -1)) FROM articles), 1), '.jpg');

    DEMO

    Решение 2.Устойчиво в конкурентной среде.

    Создаётся опорная таблица генерируемых номеров:
    CREATE TABLE image_counter (id INT AUTO_INCREMENT PRIMARY KEY);

    Триггер использует таблицу для генерации:
    CREATE TRIGGER tr_name
    BEFORE INSERT
    ON articles
    FOR EACH ROW
    BEGIN
        INSERT INTO image_counter VALUES (DEFAULT);
        SET NEW.image = CONCAT('catalog/blog-image/', LAST_INSERT_ID(), '.jpg');
        DELETE FROM image_counter;
    END

    DEMO
    Ответ написан
    Комментировать
  • Как сделать регистронезависимый поиск по longblob?

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

    Регистрозависимость операций поиска/сравнения определяется применяемым COLLATION.
    LONGBLOB имеет по умолчанию binary collation (например, utf8mb4_bin) - поэтому сравнение выполняется бинарное.
    Для регистронезависимого текстового сравнения надо явно определить требуемый COLLATION в запросе. Типа
    WHERE column COLLATE utf8mb4_0900_ai_ci LIKE 'pattern'

    Если надо ещё и charset подкорректировать, то дополнительно использовать функцию CONVERT().
    Ответ написан
    4 комментария
  • Как сделать умный поиск по базе?

    @Akina
    Сетевой и системный админ, SQL-программист.
    А если будем просто через LIKE то придет вот так (так не нужно): Иван, Ваня, Ивановы...

    Нет. Отбор записей и их сортировка - две совершенно независимые операции.
    SELECT word 
    FROM words 
    WHERE word LIKE '%$search%'
    ORDER BY LOCATE($search, word), word
    Ответ написан
    Комментировать
  • Поставить индексы на каждое поле?

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

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

    пока не понятно, какие индексы нужны, а какие нет.

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

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT b.`id`, b.`date`, l.`path` 
    FROM `buy` b
    INNER JOIN `em` e ON b.`em_id` = e.`id`
    INNER JOIN `ls` l ON FIND_IN_SET(l.`id`, b.`ls_id`)

    PS. Хранение данных в CSV - это денормализация, дурной тон, и вообще кривой переулок, ведущий прямо на поле с граблями...
    Ответ написан
    2 комментария
  • Запрос MySql. Как составить выборку из первой таблицы по нескольким параметрам из второй?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT ft.*, pt.*
    FROM fruit_table ft
    JOIN param_table pt ON ft.id=pt.id_fruit
    JOIN ( SELECT id_fruit
           FROM param_table
           WHERE id_param IN (10, 20)
           GROUP BY 1
           HAVING COUNT(DISTINCT id_param) = 2 ) ptx ON pt.id_param = ptx.id_param
    Ответ написан
    2 комментария
  • Как изменить свойства колонки, не удаляя текущие значения?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Целевое поле - вычисляемое. Значит, фраза "не удаляя её значения" по отношению к нему не имеет смысла. Даже если это поле - хранимое, а не виртуальное.
    Ответ написан
    Комментировать
  • Cортировка данных по вычислению из другой таблицы и постраничная выдача?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Нужно получать курс первого дня, для выбранного периода - first, и последнего дня - last. Чтобы высчитать разницу. После чего {last} - {first} = {Х}. И вот по этому {Х} делать сортировку выборки.

    Да запрос же тривиальный!
    SELECT DISTINCT 
           coin_uuid,
           FIRST_VALUE(price) OVER (PARTITION BY coin_uuid ORDER BY last_updated ASC) firstprice,
           FIRST_VALUE(price) OVER (PARTITION BY coin_uuid ORDER BY last_updated DESC) lastprice
    FROM exchange_rates
    ORDER BY coin_uuid, lastprice - firstprice
    Ответ написан
  • Насколько сложный пароль стоит иметь от БД?

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

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

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

    @Akina
    Сетевой и системный админ, SQL-программист.
    1. Переместить файлы таблицы.
    2. Создать пустую таблицу, скопировав CREATE TABLE с другого сервера максимально близкой версии.
    3. DISCARD TABLESPACE.
    4. Заменить файлы на сохранённые.
    5. IMPORT TABLESPACE.

    Если какая-либо таблица не удаляется либо не создаётся - попробовать провести те же операции, перегрузив сервер в режиме отключенной безопасности.

    Если всё равно не получается - бэкапить всё, что бэкапится, после чего удалить сервер и поставить заново, затем вернуть бэкап. Бэкап базы MySQL предварительно внимательно просмотреть и вычистить оттуда всё, связанное с проблемными таблицами, в отдельные файлы. При необходимости - аккуратно восстанавливать и то, что убрано, но по одному запросу за раз, и хорошо подумав, какие это может повлечь последствия.
    Ответ написан
    Комментировать
  • Откуда в MySQL Workbench постоянно берется схема mydb и как от нее избавиться?

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

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

    таблицы стали создаваться именно в ней, а не в той схеме с которой я работаю

    Если при создании таблицы указано её имя с указанием имени БД (CREATE TABLE dbname.tablename ( .. );) - таблица будет создана именно в указанной БД. Если же имя БД не указать - таблица создаётся в текущей БД. Почему у Вас именно эта БД текущая, и почему Вы не меняете её перед созданием таблиц запросом USE - это именно к Вам вопросы, и именно Ваша вина в том, что таблицы создаются "не там".
    Ответ написан
    2 комментария
  • Как получить количество записей перед определенной записью в mysql с сортировкой по полю varchar?

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

    SELECT COUNT(*)
    FROM table
    WHERE varchar_column <= @value_in_definite_row

    Или строгое неравенство, если саму "определённую запись" не учитывать.
    Ответ написан
    7 комментариев
  • Обращение к записи БД требует некоторой обработки. Что лучше: обработать в скрипте, который обратился, или в хранимой процедуре в БД?

    @Akina
    Сетевой и системный админ, SQL-программист.
    что эффективнее: хранить в записи список id объектов, которые должны быть обработаны при обращении к этой записи, в виде строки (скрипт будет парсить строку и отрабатывать каждый id), либо сделать триггер и хранимую процедуру (MySQL), которая возьмёт эту работу на себя?

    Ни то ни другое.

    Если тебе нужна канава, и есть экскаватор, то взять из его ремнабора лопату и ей копать канаву - голимая дурь. Это что касается обработки в скрипте - сервере БД сделает то же на порядок быстрее и эффективнее.

    Но есть ещё косяк - в том, как хранятся данные. Упаковка набора данных в одну запись в виде CSV-списка - это тоже дурь в подавляющем большинстве случаев. Умные люди не зря придумали нормальные формы, которые позволяют обрабатывать данные максимально эффективным образом.

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

    Насчёт триггера - сильно сомнительно, что он нужен. Триггер - это реакция на изменение данных, тогда как, судя по описанию, сигналом на обработку будет явное действие оператора без изменения данных, типа нажатия кнопки в форме. По-моему, будет достаточно если не запроса, то хранимой процедуры.
    Ответ написан
    2 комментария
  • Как получить только первые строки из групп строк отсортированной таблицы?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT prices.* 
    FROM prices
    JOIN ( SELECT size, MAX(`date`) AS `date`
           FROM prices 
           WHERE price
    --       AND `date` <= @some_date
           GROUP BY size ) AS last_nonzero_date USING (size, `date`);

    Запрос предполагает, что (size, `date`) - уникально.

    Если для size все цены нулевые (или NULL) - запись для такого размера не будет выведена.

    Если нужно состояние на определённую дату - раскомментировать WHERE.
    Ответ написан
    Комментировать
  • Как автоматизировать запуск sql скриптов?

    @Akina
    Сетевой и системный админ, SQL-программист.
    MySQL имеет собственный встроенный планировщик (MySQL 8.0 Reference Manual / Stored Objects / ...), который может делать практически что угодно. Создаёшь Event Procedure, задаёшь периодичность выполнения - остальное сервер сделает сам. Вообще без помощи/управления со стороны.

    Народ обычно любит предлагать внешние планировщики (как правило CRON) - настоятельно не рекомендую, если требующий выполнения код есть чистый SQL. Другое дело когда надо выполнять скрипты на иных языках или внешние приложения - тут да, без крона скорее всего не обойтись. Хотя и тут есть способ - подключить внешний модуль с требуемым функционалом.

    Есть папка, которая хранит в себе sql файлы для создания бд, таблиц в этой бд, импорт данных в эти таблицы.
    Как автоматизировать запуск этих sql скриптов?

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

    @Akina
    Сетевой и системный админ, SQL-программист.
    нужно удалить записи с одинаковыми date и user_id

    DELETE t1.*
    FROM tablename t1
    JOIN tablename t2 USING (date, user_id)
    WHERE t1.id > t2.id


    а лучше не создавать их

    CREATE UNIQUE INDEX indexname ON tablename (date, user_id)

    Выполнить строго после удаления дубликатов - иначе упадёт по ошибке.
    Ответ написан
    Комментировать
  • Как оптимизировать sql запрос (MySQL)?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Не используйте картезианское произведение - нечитаемо. Используйте нормальный JOIN-синтаксис:
    SELECT `p`.`sum`, `p`.`type`, `p`.`visit` 
    FROM `visits` AS `v`
    JOIN `payments` AS `p` ON `v`.`id` = `p`.`visit` 
    WHERE DATE(p.date) = '2021-10-04' AND `v`.`office` = '1'


    Соответственно для оптимизации запроса требуется:

    1. избавиться от функции в условии отбора и конвертировать его в вид
    SELECT `p`.`sum`, `p`.`type`, `p`.`visit` 
    FROM `visits` AS `v`
    JOIN `payments` AS `p` ON `v`.`id` = `p`.`visit` 
    WHERE p.date >= '2021-10-04' 
      AND p.date < '2021-10-05' 
      AND `v`.`office` = '1'

    2. Создать индексы:

    2a. visits (office, id).
    2b. payments (`date`, visit) и payments (visit, `date`), посмотреть какой из них используется, удалить неиспользуемый.

    3. Если поле `v`.`office` имеет числовой тип, изменить условие отбора по этому полю на AND `v`.`office` = 1. В исходном виде, если поле числовое, то и поле, и значение приводятся к floating-point number, и только потом сравниваются.
    Ответ написан
  • Как удалить primary key с auto increment?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если поле объявлено как AUTO_INCREMENT, то оно ОБЯЗАНО быть первичным ключом либо его префиксом. Если удалить PRIMARY KEY, но НЕ удалить AUTO_INCREMENT, результирующая структура не будет отвечать этому требованию - поэтому возникает ошибка.

    Следовательно, в одном ALTER TABLE следует выполнить обе операции - и удалить первичный ключ, и атрибут AUTO_INCREMENT (например, изменить на DEFAULT {значение}). Либо выполнить два ALTER TABLE, но в обратном порядке - сначала удалить атрибут AUTO_INCREMENT, и только потом первичный ключ.

    DEMO
    Ответ написан
    1 комментарий
  • Как объединить два SQL запроса в один?

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

    SELECT p.*, GROUP_CONCAT(c.name) countries
    FROM p
    JOIN с ON FIND_IN_SET(c.id, p.country)
    GROUP BY p.id

    Если в поле p.country к тому же имеются паразитные пробелы- перед связыванием их необходимо удалить.

    Настоятельный совет - нормализовать данные. CSV - это крайне неудачное решение.
    Ответ написан
    1 комментарий