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

    @Akela_wolf
    Extreme Programmer
    Если у вас неограниченная вложенность, то только через рекурсивный запрос. MySQL 8 научился их делать. Это позволит вам рекурсивно собрать в одном из полей запроса данные из зависимых таблиц. Вот документация

    Вот пример:
    CREATE TABLE cat(
      id INT NOT NULL PRIMARY KEY,
      title VARCHAR(100) NOT NULL,
      parent_id INT NULL
    );
    
    INSERT INTO cat VALUE (1, 'Root1', NULL), (2, 'Root2', NULL), (3, 'Child1', 1),
    (4, 'Child2', 3), (5, 'Child3', 2);
    
    WITH RECURSIVE rcat(id, title, path) AS (
      SELECT cat.id, cat.title, CAST(cat.id AS CHAR(200)) FROM cat WHERE parent_id IS NULL
      UNION ALL
      SELECT cat.id, cat.title, CONCAT(rcat.path, ',', cat.id) FROM cat JOIN rcat ON cat.parent_id=rcat.id
    )
    SELECT * FROM rcat WHERE id=4;


    Пример
    Ответ написан
    7 комментариев
  • Проблема с объединением нескольких таблиц MySQL?

    @Akela_wolf
    Extreme Programmer
    Во-первых, стрелки на диаграмме принято рисовать в другую сторону - это таблица связи ссылается на таблицу продуктов и на таблицу фотографий.
    Во-вторых, то чего вы хотите, сделать можно но это неправильный путь. Правильных путей тут два:
    1. Построить запрос, который выбирает продукты по определенному условию и присоединяет к ним картинки. В этом случае у вас будет несколько записей на один продукт, отличающихся только картинками (это, я так понимаю, вы сумели сделать). Обрабатывать это не очень удобно, но зато один запрос в БД.
    2. Выбрать сначала продукты, а затем к продуктам выбрать фотографии. Потребуется сопоставить фотографии с продуктами (по ID) на уровне приложения. Зато два запроса в БД и каждый возвращает свой набор требуемых данных.


    Третий правильный путь - использовать ORM, которая возьмет на себя извлечение данных из БД.

    Неправильный (на мой взгляд) путь - использовать агрегирующие функции, как-то так:
    SELECT p.*, JSON_ARRAYAGG(f.filename) AS files FROM product p
    LEFT JOIN product2file p2f ON p2f.product_id=p.id
    LEFT JOIN file f ON p2f.file_id=f.id
    GROUP BY p.id;

    Пример

    Но я считаю этот путь неправильным, потому что: с ростом сложности БД сложность подобных запросов быстро растет и тут начинают вылазить ошибки. А еще потому что вытащить из подчиненной таблицы 2 колонки можно, но порядок элементов в функции JSON_ARRAYAGG не определен, поэтому начинается возня с тем чтобы все это сопоставить. GROUP_CONCAT тоже имеет проблемы (в первую очередь ограничение длины).

    Так что, мне кажется, лучше привыкать к тому что запрос может возвращать несколько строк для одной сущности и учиться с этим работать на уровне приложения, чем извращаться в запросе.
    Ответ написан
    Комментировать
  • Как в результатах запроса колонку превратить в строку?

    @Akela_wolf
    Extreme Programmer
    Если известно количество устройств (и соответственно количество колонок в итоговой таблице) - можно. Пример для 4 устройств:
    CREATE TABLE data(
      device INT NOT NULL,
      date DATETIME NOT NULL,
      metric NUMERIC(10,2) NOT NULL
    );
    
    INSERT INTO data VALUES (1, '2022-01-01 00:00:00', 2.34),
    (2, '2022-01-01 00:00:00', 1.23),
    (3, '2022-01-01 00:00:00', 3.82), 
    (4, '2022-01-01 00:00:00', 0.45),
    (1, '2022-01-01 01:00:00', 2.00),
    (2, '2022-01-01 01:00:00', 1.82),
    (3, '2022-01-01 01:00:00', 3.09);
    
    SELECT date, SUM(d1), SUM(d2), SUM(d3), SUM(d4) FROM (
    SELECT date,
    CASE WHEN device=1 THEN metric ELSE NULL END AS d1,
    CASE WHEN device=2 THEN metric ELSE NULL END AS d2,
    CASE WHEN device=3 THEN metric ELSE NULL END AS d3,
    CASE WHEN device=4 THEN metric ELSE NULL END AS d4
    FROM data
    ) nested
    GROUP BY date;


    https://sqlize.online/sql/mysql80/68e677a2fc577e6c...
    Ответ написан
    2 комментария
  • Как исправить "subquery returns more than 1 row" в "after update" триггере?

    @Akela_wolf
    Extreme Programmer
    А что вы пытаетесь тут сделать? Вот конкретно этот подзапрос (SELECT id FROM test1) он для чего? Вы выбираете все записи из таблицы test1, что, как бы, очень подозрительно. А если там будет миллион записей?

    У вас в триггере есть переменные NEW и OLD, указывающие на обновленную запись в таблице test1 - вот и используйте их, чтобы определить какие записи в таблице test2 вам нужно обновить.
    Ответ написан
    2 комментария
  • Почему выдает ошибку 1442?

    @Akela_wolf
    Extreme Programmer
    Сделайте триггер BEFORE INSERT и задайте значение полям объекта NEW (как это и предполагается таким триггером by design)
    Ответ написан
    Комментировать
  • SQL запрос, как осуществить выборку данных одним махом?

    @Akela_wolf
    Extreme Programmer
    SELECT p.* FROM peoples p --выбираем людей, для которых
    WHERE NOT EXISTS ( --не существует
      SELECT 1 FROM cars c --машины
      WHERE c.peoples_id = p.id --принадлежаший этому человеку
      AND c.desc IN ('Mercedes', 'BMW') --и которая мерседес или бмв
    )


    Заменив NOT EXISTS на EXISTS можно получить обратный список - тех у кого есть мерс или бмв.
    В случае поиска людей у которых НЕТ - полный аналог приведенного в ответе Rsa97 варианта с LEFT JOIN. Но в случае поиска людей у которых ЕСТЬ - вариант с LEFT JOIN может давать дублирующиеся строки, вариант с EXISTS всегда возвращает не более одной строки для каждого человека.
    Ответ написан
    Комментировать
  • Как обновить данные в одной таблице, после обновления данных в другой?

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

    @Akela_wolf
    Extreme Programmer
    Потому что тег ID=3 принадлежит не только посту 33. Вот и получаете что есть запись в которой он принадлежит и запись в которой не принадлежит. А если будет 3 поста - будет 3 такие записи (в одной принадлежит и в двух не принадлежит) и т.д.

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

    Получить список тегов, которые принадлежат посту:
    SELECT t.* FROM tags t 
    JOIN posts_tags pt ON pt.tag_id=t.id
    WHERE pt.post_id=:post_id

    Получить список тегов, которые не принадлежат посту:
    SELECT t.* FROM tags t 
    LEFT JOIN posts_tags pt ON pt.tag_id=t.id AND pt.post_id=:post_id
    WHERE pt.id IS NULL

    Если хочется завернуть это в один запрос - добавляете колонку have_tag (в первом запросе - 1, во втором - 0) и делаете UNION.
    Ответ написан
  • Как правильно составить SQL запрос с использованием order by case?

    @Akela_wolf
    Extreme Programmer
    Добавить условие WHERE title LIKE '%Спиннинг%'
    Ответ написан
    Комментировать
  • Как переносятся базы данных Postgresql и Mysql?

    @Akela_wolf
    Extreme Programmer
    Эспортируете данные в SQL (см. mysqldump, pg_dump). На целевой системе - загружаете полученный SQL.
    Ответ написан
    Комментировать
  • Как защититься от таких инъекций или как они называются?

    @Akela_wolf
    Extreme Programmer
    Это называется XSS. Защищаются от нее путем фильтрации вводимого пользователем содержимого. Самое простое - экранировать HTML-теги, чтобы они выводились пользователю как текст, а не как HTML-код. Более сложный вариант - оставлять только безопасные теги, которые пользователь может использовать для оформления комментария (полужирный шрифт, курсив, подчеркивание, цвет шрифта и т.д.). Для этого есть готовые библиотеки, если будете писать самостоятельно - велик шанс что упустите какой-нибудь corner case и оставить "дырку" в сайте.
    Ответ написан
  • Как изменить 1200 строк в таблице?

    @Akela_wolf
    Extreme Programmer
    Как вариант:
    UPDATE product SET `alias`=transliterate(title);

    Хранимую функцию transliterate придется написать самостоятельно (или найти в интернете, они есть)
    Ответ написан
    Комментировать
  • Не могу получить доступ к MSQL?

    @Akela_wolf
    Extreme Programmer
    spring.datasource.url=<jdbc string>
    spring.datasource.username=<username>
    spring.datasource.password=<password>

    За остальными опциями см. документацию спринга.
    Ответ написан
    Комментировать