Задать вопрос
  • 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-программист.
    Покупаешь ещё один роутер (конечно, уж не совсем дерьмо). Каскадишь. Батя прячется за ним (у него двойной NAT, "две защиты за те же деньги", ибо второй роутер ты покупаешь на свои) и не даёт тебе пароля, а ты сидишь только за первым, и если твой комп поимеют, то до батиного не доберутся.
    Ответ написан
    6 комментариев
  • Разграничить по подсетям и VLAN?

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

    PS. Не мешайте VLAN и подсети - это вещи с разных уровней. Ничто не мешает нескольким подсетям бегать внутри одного VLAN. И даже наоборот.
    Ответ написан
  • Как быстрее подсчитать пересечение в таблице?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Пример реализации "влоб" (синтаксис MySQL).

    Структура:
    CREATE TABLE test ( word0 VARCHAR(255),
                        word1 VARCHAR(255),
                        word2 VARCHAR(255),
                        word3 VARCHAR(255)
    );


    Запрос:
    WITH 
    cte1 AS (
        SELECT *, ROW_NUMBER() OVER () identity
        FROM test
    ),
    cte2 AS (
        SELECT word0 word, identity FROM cte1 UNION ALL
        SELECT word1 word, identity FROM cte1 UNION ALL
        SELECT word2 word, identity FROM cte1 UNION ALL
        SELECT word3 word, identity FROM cte1 
    )
    SELECT LEAST(t1.word, t2.word), GREATEST(t1.word, t2.word), COUNT(DISTINCT identity)
    FROM cte2 t1
    JOIN cte2 t2 USING( identity )
    WHERE t1.word > t2.word
    GROUP BY 1, 2;

    DEMO fiddle

    Но надо чётко понимать что на заявленных объёмах запрос умрёт навсегда, вместе с сервером.

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

    @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).
    Ответ написан
    Комментировать
  • Как создать тригер для дефолтного значения?

    @Akina
    Сетевой и системный админ, SQL-программист.
    CREATE TABLE trs (
        wallet_id INT, 
        amount DECIMAL(12, 2), 
        hash BYTEA GENERATED ALWAYS AS (sha256((wallet_id + amount) :: TEXT :: BYTEA)) STORED
    )

    из конкатенированный строки wallet_id + hash

    Вообще-то оба поля чисельные - какая в пень конкатенация-то? Но если их надо преобразовать в строку и конкатенировать, то
    CREATE TABLE trs (
        wallet_id INT, 
        amount DECIMAL(12, 2), 
        hash BYTEA GENERATED ALWAYS AS (sha256((wallet_id :: TEXT || amount :: TEXT) :: BYTEA)) STORED
    )
    Ответ написан
    1 комментарий
  • Rак записать id в Postgres?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Использовать надо INSERT .. SELECT
    WITH cte_id  AS (
        INSERT INTO words (name_word, discription_word) 
        VALUES ('cool', 'круто') 
        RETURNING Id
    )
    INSERT INTO users_words (users_id, words_id, status_learn_word)
    SELECT 649651821, id , 0
    FROM cte_id;
    Ответ написан
    Комментировать
  • 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 комментария
  • В чем ошибка sql-запроса?

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

    Формально запрос содержит несколько ошибок и недочётов.

    • Основная ошибка, вернее, опечатка - это WARCHAR вместо VARCHAR. Она фатальна.
    • Вторая по тяжести ошибка - это использование служебного слова number в качестве имени поля. В части диалектов SQL это слово - зарезервированное, и тогда эта ошибка тоже фатальна.
    • Третье - это скорее не ошибка, а самообман. Речь об указании длины для полей типа INT. В подавляющем большинстве диалектов, где указание длины допускается, оно просто игнорируется, а потому указание просто не имеет смысла. Если для поля number требуется ограничить возможные значения двумя цифрами, разумнее использовать поле типа TINYINT с соответствующим CHECK constraint.
    • Ну и длина поля типа VARCHAR - опять же ограничение в 55 символов разумнее делать с помощью CHECK constraint, а длину поля задавать максимальную, не приводящую к увеличению потребляемого дискового пространства. С учётом того, как хранятся строки переменной длины, VARCHAR(255) в большинстве диалектов будет наилучшим решением.
    Ответ написан
    Комментировать
  • Как найти строку по значению и изменить соседнее значение?

    @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...
    Ответ написан
    Комментировать
  • В чем отличие ACL от Firewall?

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

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

    @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 комментарий
  • Доказано ли, и можно ли сжать произвольные данные до 20 байтов к примеру?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Допустим, существует некий алгоритм, который преобразует последовательность X длины M в последовательность Y, причём существует обратное преобразование. Неважно, что это за алгоритм конкретно - сжатие, создание "зерна" и пр. Но очевидно, что:

    1. Количество вариантов последовательности X составляет K в степени M, где K - размер словаря, т.е. количество возможных различимых значений одного элемента последовательности X. В случае байтовой последовательности это байт, т.е. K=256.

    2. Каждая последовательность X после преобразования даёт последовательность Y, причём две разные последовательности X дают разные последовательности Y.

    Соответственно количество возможных последовательностей Y равно количеству возможных последовательностей X. И соответственно если существует хотя бы одна последовательность Y короче последовательности X, то существует хотя бы одна последовательность Y длиннее последовательности X.

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

    Что же до "зерна", которое разворачивается в гигабайты - во-первых, количество финальных миров определяется количеством значений "зерна", то есть вовсе даже не такое бесконечно большое, как кажется, во-вторых, созданный образ мира содержит значительное число повторяющихся элементов, а создание копий - это немножко не декомпрессия.
    Ответ написан
    Комментировать
  • Как отсортировать запрос с 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 комментарий
  • Как сделать SQL выборку по максимальной дате?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если текущая версия СУБД поддерживает оконные функции - то ROW_NUMBER() в CTE и отбор по rn=1 во внешнем запросе.
    WITH cte AS (
        SELECT *, ROW_NUMBER() OVER (PARTITION BY list_name ORDER BY date DESC) rn
        FROM table
        )
    SELECT *
    FROM cte
    WHERE rn = 1

    Если не поддерживает - агрегирующий подзапрос, который для каждой категории получает максимальную дату, и отбор записей по этим значениям из другой копии таблицы.
    SELECT t1.*
    FROM table t1
    NATURAL JOIN (
        SELECT list_name, MAX(date) date
        FROM table
        GROUP BY 1
        )

    Оба запроса предполагают уникальность (list_name, date).
    Ответ написан
    Комментировать
  • Можно ли в postgres выполнить условную сортировку?

    @Akina
    Сетевой и системный админ, SQL-программист.
    select * 
    from products 
    order by type ASC,
             case WHEN type = 'books' then id      ELSE 0 END desc,
             case WHEN type = "food"  then name    ELSE 0 END asc,
             case WHEN type = "food"  then price   ELSE 0 END desc,
             case WHEN type = "relax" THEN popular ELSE 0 END asc,
             case WHEN type = "relax" THEN id      ELSE 0 END desc
    Ответ написан
    Комментировать