Задать вопрос
  • Как найти в mysql ряд где значение json массива равно значению?

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

    SELECT id, CAST(array_test AS CHAR) array_test 
    FROM test
    WHERE JSON_OVERLAPS(array_test, CAST('[2]' AS JSON));


    DEMO fiddle

    PS. Да, там именно запятая. И знак - именно восклицательный.
    Ответ написан
    Комментировать
  • Пользователи и рабочий график: как хранить?

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

    Налицо тривиальная связь типа "много-ко-много". И соответственно хранение - две таблицы связываемых сущностей и связующая таблица. Т.е.

    1) User (user_id, name, ...);
    2) Dates (date, type, ...);
    3) UsersDates (user_id references User (user_id), date references Dates (date));
    Ответ написан
  • Как побороть ошибку #1032 - Невозможно найти запись?

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

    DEMO

    Походу, это phpmyadmin в очередной раз показал своё свиное рыло...
    Ответ написан
    Комментировать
  • Как правильно составить запрос для поиска по JSON полю в mySql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    запрос для выборки всех записей у которых в поле 'condition' есть "action": "6"

    SELECT DISTINCT action.*
    FROM action
    CROSS JOIN JSON_TABLE(action.`condition`,
                          '$[*].action' COLUMNS (action INT PATH '$')) jsontable
    WHERE jsontable.action = 6


    https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=c3e97c...
    Ответ написан
    Комментировать
  • Как сгрупировать значения по колонке?

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

    61239ab99d4b7647714934.png
    Ответ написан
    Комментировать
  • Ping до роутера какой должен быть?

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

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

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

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

    WITH 
    cte1 AS ( SELECT t1.ts, t1.val,
                     t2.ts ts_before, t2.val val_before,
                     t3.ts ts_after, t3.val val_after
              FROM test t1
              JOIN test t2 ON t1.ts >= TIMESTAMP(t2.ts, @delta)
              JOIN test t3 ON t1.ts <= TIMESTAMP(t3.ts, @delta) ),
    cte2 AS ( SELECT *, 
                     ROW_NUMBER() OVER (PARTITION BY ts ORDER BY ts_before DESC) rn_before, 
                     ROW_NUMBER() OVER (PARTITION BY ts ORDER BY ts_after ASC) rn_after
              FROM cte1 )
    SELECT ts,
           val,
           ts_before,
           val_before,
           ts_after,
           val_after,
           CASE WHEN val_after = val_before
                THEN val_before
                ELSE val_before + (val_after - val_before) / TIMESTAMPDIFF(SECOND, ts_after, ts_before) * TIMESTAMPDIFF(SECOND, ts, TIMESTAMP(ts_before, @delta)) 
                END val_approximated
    FROM cte2 
    WHERE ts > '2021-01-02'
          AND rn_before = 1
          AND rn_after = 1


    DEMO fiddle с некоторыми пояснениями.

    Тормозить, конечно, на большом массиве будет нещадно - так что неплохо бы ещё в первом CTE по всем трём копиям задать вменяемые границы от и до...

    Не имел дела раньше с оконными функциями в MySQL.

    А придётся. И не просто "иметь дело", а хорошо изучить, до полного понимания.
    Ответ написан
    2 комментария
  • Как удалить кортеж из массива по значению кортежа?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Поделить на элементы, отбросить ненужные, собрать обратно:
    WITH cte AS (SELECT 1 id, CAST('[12, 13, {"12": 123} ]' AS JSON) sort)
    SELECT cte.id, JSON_ARRAYAGG(jsontable.element) sort
    FROM cte
    CROSS JOIN JSON_TABLE(cte.sort,
                          '$[*]' COLUMNS (element JSON PATH '$')) jsontable
    WHERE jsontable.element != CAST('{"12": 123}' AS JSON)
    GROUP BY cte.id

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

    PS. Сравнение объектов JSON - занятие неблагодарное. В более сложных случаях не пройдёт, даже JSON_OVERLAPS() может не спасти. Возможно, использование строковых функций на строковом представлении JSON более правильное решение.
    Ответ написан
    Комментировать
  • Зачем нужны внешние ключи прописанные в структуре БД (MySQL) - они действительно там нужны?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Любая СУБД имеет достаточно мощную систему контроля целостности и непротиворечивости данных. Эта система работает, используя набор правил контроля, описанных в структуре БД, и жёстко следит за тем, чтобы ни одно из правил не было нарушено.

    Внешний ключ - это как раз такое правило. Сформулировано оно так: в данном поле таблицы не может храниться значение, которое не присутствует в той таблице, на которую ссылается внешний ключ (rонечно, в зависимости от конкретного текста ссылки внешнего ключа и самого поля тут возможны варианты - например, в этом поле может храниться не только значение, присутствующее в ссылочной таблице, но и NULL). И, имея такое правило, СУБД ни при каких условиях не позволит его нарушить. Любая попытка вставить запись со значением, которого нет в ссылочной таблице, приведёт к ошибке. Любая попытка изменить существующее значение на такое, которого "там" нет - приведёт к ошибке. То же касается и "второй" стороны, СУБД не позволит изменить значение в ссылочной таблице или удалить его (потому что записи в нашей таблице при этом "потеряют" ссылку) - такая попытка корректировки приведёт к ошибке.
    Ответ написан
    2 комментария
  • Как синхронизировать две mysql базы?

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

    На " другом сервере, где вертится аналитика самописная", перезапускаете MySQL, включив FEDERATED Engine. Далее создаёте подключение (CREATE SERVER), создаёте копию удалённой таблицы на этом сервере - и просто копируете из неё записи за последний месяц. Либо без сервера - прямо при создании таблицы указываете параметры подключения.
    Ответ написан
  • Алгоритм поиска минимального количества ходов, требуемых для приведения всех элементов к одному числу (Python)?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если количество элементов массива нечётно, то тем значением, к которому надо привести элементы, равно значению строго среднего элемента (медианы массива).

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

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

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

    Имя пользователя - задаётся пользователем при подключении. Хост (имя либо адрес) определяется сервером MySQL. самостоятельно, и на этот процесс пользователь почти не имеет возможности повлиять. Объединение этих двух частей и даст полное имя, которое будет использоваться для определения привилегий.

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

    Подробно всё это объясняется в документации в разделе Access Control and Account Management.
    Ответ написан
    Комментировать
  • Как правильно выстроить отношения и спроектировать таблицы?

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

    Первая описывает связь типа много-ко-много между компанией и ролью. Ведь в разных компаниях может быть разный набор ролей - где-то есть аудитор, а где-то нет, к примеру...

    Вторая описывает связь типа много-ко-много между пользователем и первой таблицей.

    Вместе они задают, какую конкретную роль в конкретной компании имеет конкретный пользователь.
    Ответ написан
    5 комментариев
  • Как вносить в ячейку значение зависимое от даты?

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

    Формулы:

    G1=TODAY()-1
    G5:I5=VLOOKUP($G$1;$A$2:$D$11;COLUMN()-5;0)


    То же, если конечная таблица на другом листе:

    6113d3ba2580f247139272.png
    Ответ написан
    Комментировать
  • Postgresql, как получить строки таблицы, попадющие под интервалы записанные в таблице с интервалами?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Полное ощущение, что нужно нечто типа
    SELECT [DISTINCT] t.*
    FROM t
    JOIN t_intervals ti ON t.sequence BETWEEN ti.start AND ti.end
    WHERE ti.id in (2,10,30, ..., n)

    Если интервалы в t_intervals гарантированно не пересекаются (хотя я лично фиг знает как это организовать в виде констрейнтов, а триггерная логика - ниачём), то DISTINCT не требуется.
    Ответ написан
    Комментировать
  • Как вывести последние сообщение?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если ориентироваться на пример, а не на описание задания, то
    WITH
    cte AS ( SELECT *, 
                    ROW_NUMBER() OVER (PARTITION BY sender, receiver ORDER BY created_at DESC) rn
             FROM message )
    SELECT u1.username sendername,
           u2.username receivername,
           cte.text_message,
           cte.created_at
    FROM cte 
    JOIN users u1 ON cte.sender = u1.id
    JOIN users u2 ON cte.receiver = u2.id
    WHERE cte.rn = 1

    https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a7a647...
    Ответ написан
    1 комментарий
  • В чем различие 2х запросов?

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

    В остальном именно эти два запроса абсолютно эквивалентны с точностью до порядка выполнения. Операция "запятая" имеет приоритет ниже, чем операция JOIN, т.е. в первом запросе выполняется неявное STRAIGHT_JOIN. И если СУБД не умеет наплевать на это, первый запрос может порождать неоптимальный план выполнения даже при актуальной статистике данных.

    В более сложных запросах использование запятой, особенно в комбинации с JOIN, вообще способно полностью поломать запрос, вплоть до синтаксической некорректности. А потому настоятельно рекомендуется вместо запятой использовать CROSS JOIN.
    Ответ написан
    Комментировать
  • Проблема с regexp на mysql 8.0.26?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Согласно MySQL 5.7 Reference Manual / ... / Regular Exp...

    [[:<:]], [[:>:]]

    These markers stand for word boundaries.


    Согласно MySQL 8.0 Reference Manual / ... / Regular Exp...

    The Spencer library supports word-beginning and word-end boundary markers ([[:<:]] and [[:>:]] notation). ICU does not. For ICU, you can use \b to match word boundaries; double the backslash because MySQL interprets it as the escape character within strings.


    Так что подход правильный.

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

    @Akina
    Сетевой и системный админ, SQL-программист.
    1. Вот оно надо, каждый раз заботиться об установлении значений полей DATE_CREATE/DATE_UPDATE?

    ALTER TABLE tablename
    MODIFY COLUMN date_create TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    MODIFY COLUMN date_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

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

    2. Для выполнения операции используем рекурсивный CTE (помним, что поля DATE_CREATE/DATE_UPDATE сами заботятся о правильном значении, как и автоинкрементный первичный ключ):

    INSERT INTO tablename (active, user_id, value)
    WITH RECURSIVE
    cte AS ( SELECT 1 num
             UNION ALL
             SELECT num + 1 FROM cte WHERE num < 9999 )
    SELECT 1, 1, num
    FROM cte;


    Возможно, предварительно надо установить достаточное значение для сессионной переменной:SET SESSION cte_max_recursion_depth = 10000;

    Если версия MySQL старая и не понимает CTE, то

    INSERT INTO tablename (active, user_id, value)
    SELECT 1, 1, 1 + t1.num + t2.num * 10 + t3.num * 100 + t4.num * 1000 AS value
    FROM       (SELECT 0 num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1
    CROSS JOIN (SELECT 0 num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2
    CROSS JOIN (SELECT 0 num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3
    CROSS JOIN (SELECT 0 num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4;
    HAVING value <= 9999;
    Ответ написан
    1 комментарий
  • Как правильно спроектировать связь БД между двумя товарами?

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

    CREATE TABLE groups_of_goods (
        group_id BIGINT UNSIGNED NOT NULL,
        product_id BIGINT UNSIGNED NOT NULL,
        PRIMARY KEY (group_id, product_id),
        FOREIGN KEY fk_product (product_id) REFERENCES product (product_id)
    );


    Соответственно если твои труселя входят в одну группу и ссылаются друг на друга, то в таблице будут 2 записи - (123, 10) и (123, 15).

    Кстати, такая схема обеспечивает и принцип "вассал моего вассала ...". Т.е. "пиджак малиновый" может ссылаться на "брюки малиновые" (через группу 456) и "пиджак в полоску" (через группу 789), но при этом последние два друг на друга ссылаться не будут, ибо разные группы.
    Ответ написан
    2 комментария