Ответы пользователя по тегу MySQL
  • 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 комментарий
  • Как работает GROUP BY?

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

    Например, пишу я такой SELECT и все нормально
    SELECT Trip.plane, Trip.id


    Ну да, тебе нужны отдельные самолёты, соответственно никакие группы не нужны. GROUP BY не требуется.

    Но при таком мне выдает ошибку
    SELECT Trip.plane, COUNT(Trip.plane) planes

    А вот теперь ты хочешь, поделив все имеющиеся самолёты на группы, собрав в каждую группу самолёты одного типа, посчитать в каждой группе количество самолётов. И для того, чтобы указать, по какому признаку нужно делить на группы, требуется GROUP BY.
    Ответ написан
    2 комментария
  • Откуда берется /*!40001 SQL_NO_CACHE */ в запросе при создании дампа?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Отвечу всё же на заданный вопрос:
    Откуда это берется вообще? /*!40001 SQL_NO_CACHE */ и как это убрать?

    Это - комментарий с фрагментом запроса, специфичным для MySQL.

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

    Опциональное пятизначное число указывает минимальную версию MySQL, начиная с которой содержимое комментария должно обрабатываться (в показанном фрагменте - это версия 4.00.01), на более младшей версии комментарий останется комментарием. При его отсутствии (используется только /*!) - код из комментария обрабатывается любой версией.

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

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

    С точки зрения работы с СУБД хранение массива данных в виде CSV-значения - крайне неудачный вариант. И весьма проблемный в обработке. Впрочем, если речь идёт о достаточно статичном массиве данных в сотню записей - вариант допустимый.

    Нормализованная структура, удобная в обработке, может выглядеть, например, так (само собой, это только кусок для хранения слов и фраз):
    CREATE TABLE words (
        word_id INT AUTO_INCREMENT PRIMARY KEY,
        word VARCHAR(255) UNIQUE NOT NULL
    );
    
    CREATE TABLE phrase (
        phrase_id INT NOT NULL,
        FOREIGN KEY (phrase_id) REFERENCES phrases (phrase_id),
        word_id INT NOT NULL,
        FOREIGN KEY (word_id) REFERENCES words (word_id),
        word_position INT,
        PRIMARY KEY (phrase_id, word_position)
    );
    Ответ написан
  • Экспорт данных из QUIK по ODBC. Как налету преобразовывать VARCHAR-поля в правильные (DATE, DECIMAL, ENUM)?

    @Akina
    Сетевой и системный админ, SQL-программист.
    В тексте запроса ЛЮБЫЕ данные представлены как их строковые представления. Да что там - сам SQL-запрос есть строковый литерал.

    Поэтому следует озаботиться исключительно правильным представлением. Форматом. Если данные - число, то десятичным разделителем должна быть точка. Если это дата или строка - должны присутствовать обрамляющие кавычки, причём дата должна быть в формате, понятном текущей СУБД (предпочтительно YYYY-MM-DD - этот формат понимают все СУБД), а в строке должны быть экранированы все символы, являющиеся служебными. И т.п.

    Если выгруженные данные не соответствуют этому формату, то в запросе на добавление можно использовать не напрямую значение (и потом маяться дурью в процедуре/триггере), а, используя встроенные функции, преобразовать данные к правильному типу. Например, если в поле надо вставить число, а в выгрузке использована запятая в качестве разделителя, это будет
    INSERT ... VALUES ( ... , CAST(REPLACE(@value, ',', '.') AS DOUBLE), ...
    Ответ написан
    Комментировать
  • Как связать много сущностей к одной в результате?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT for_output
    FROM ( SELECT name AS film_name, name AS for_output
           FROM films
         UNION ALL
           SELECT films.name, comments.comment
           FROM films 
           JOIN comments USING (film_id) ) total
    ORDER BY film_name, film_name <> for_output
    Ответ написан
    Комментировать
  • Почему долгий запрос delete к таблице сильно тормозит запросы insert к другим таблицам?

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

    Организуйте удаление пакетами. Скажем, по 10к записей.
    CREATE PROCEDURE delete_rows()
    BEGIN
        SELECT @@autocommit INTO @autocommit;
        SET SESSION autocommit = ON;
        REPEAT
            DELETE FROM bigtable WHERE state=2 LIMIT 10000;
            SELECT SLEEP(1) INTO @tmp;
        UNTIL NOT ROW_COUNT() END REPEAT;
        SET SESSION autocommit = @autocommit;
    END
    Ответ написан
    Комментировать
  • Как составить запрос к MYSQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT UserID, t1.CountMessage-t2.CountMessage
    FROM daily_exp_snapshots t1
    JOIN daily_exp_snapshots t2 USING (UserID)
    WHERE t1.date_added >= CURRENT_DATE
      AND t1.date_added < CURRENT_DATE + INTERVAL 1 DAY
      AND t2.date_added >= CURRENT_DATE - INTERVAL 1 DAY
      AND t2.date_added < CURRENT_DATE
    Ответ написан
    Комментировать
  • Как выбрать конкретную строку из Mysql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT SUBSTRING_INDEX(SUBSTRING(full FROM 30 + LOCATE('https://www.youtube.com/embed/', full)), '"', 1)
    FROM params
    WHERE LOCATE('https://www.youtube.com/embed/', full)
    -- AND id=247397
    Ответ написан