Ответы пользователя по тегу MySQL
  • Подскажите SQL-запрос для выборки пользователей по их опциям

    FloppyFormator
    @FloppyFormator
    А чтобы тут не было слишком скучно, предложу ещё одно решение для MySQL:

    SELECT user_id FROM user_option GROUP BY user_id HAVING GROUP_CONCAT(DISTINCT option_id ORDER BY user_id ASC SEPARATOR ',') = '1,2,3,4,5';
    
    Ответ написан
    1 комментарий
  • Как ограничить произвольный mysql запрос только SELECT командой?

    FloppyFormator
    @FloppyFormator
    Грант на селект, конечно, самое адекватное решение.
    Как вынужденная мера, можно попробовать анализировать введённый запрос и на основании результата передавать либо не передавать его СУБД.
    Но я бы предложил обратную процедуру: конструировать запрос из имеющихся данных, введённых любым удобным способом, в том числе и парсингом исходного запроса. Главное, передавать СУБД не введённые извне данные, а специально сформированный запрос, в котором гарантированно не будет «неправильных» конструкций. А если таковые есть в исходном запросе, выдавать ошибку.
    Ответ написан
    Комментировать
  • Как составить «хитрый» MySQL запрос?

    FloppyFormator
    @FloppyFormator
    Итак, исправляю сам себя.

    Чтобы в наш интервал не попали 16 часов, он целиком должен помещаться между двумя ближайшими 16-часовыми отметками на временной прямой. Их можно получить искусственно: первая отметка это наиболее поздние дата-время, когда было 16 часов, но не позже, чем start, а вторая — ровно на сутки позже. Назовём условно эти отметки a и b. Так как start всегда попадает в [a, b], вся задача сводится к проверке попадания end в интервал [a, b]. При end < b в интервале [start, end] не будет ни одной 16-часовой отметки. Теперь вернёмся к исходной задаче. Обращаем условие: при end >= b в интервал [start, end] попадёт хотя бы одна отметка в 16 часов.

    Теперь постараемся получить b. Чтобы получить a, вычтем из start 16 часов, обнулим временную часть (прыгнув таким образом к началу суток) и прибавим обратно 16 часов. Величину b получить ещё проще: прибавляем сутки к a.

    И в SQL:
    SELECT *
    FROM my_table
    WHERE
        end >= DATE( start - INTERVAL '16:00:00' HOUR_SECOND ) + INTERVAL '16:00:00' HOUR_SECOND + INTERVAL 1 DAY
    
    Ответ написан
  • Как составить «хитрый» MySQL запрос?

    FloppyFormator
    @FloppyFormator
    Предлагаю идти от обратного: в какой интервал не попадает время 16 часов? Только в такой, который целиком помещается между 16 часами первого и следующего дня. То есть, нужно проверить, попадает ли наш интервал в этот промежуток. Пересечение интервалов [a, b] и [c, d] легко проверяется условием a <= d && b >= c. В нашем случае, start >= next_date_16_00 && end <= start_date_16_00, где start_date_16_00 — 16 часов в день начала интервала, а next_date_16_00 — то же, но на следующие сутки. Обращаем условие (мы ведь начинали от обратного): start < next_date_16_00 || end > start_date_16_00.

    И наш запрос:
    SELECT *
    FROM my_table
    WHERE
        start < TIMESTAMP( DATE(start) + INTERVAL 1 DAY, '16:00:00' ) OR
        end > TIMESTAMP( DATE(start), TIME('16:00:00') )
    
    Ответ написан
    1 комментарий
  • MySql - добавление N строк по условию

    FloppyFormator
    @FloppyFormator
    Пока тут тихо и незаметно обсуждали составные ключи, в порядке развлечения предложу второй вариант:

    INSERT INTO char_use (shot_id, char_id)
    SELECT shot.id, 9
    FROM shot
    LEFT JOIN char_use ON shot.shot_id = char_use.shot_id
    WHERE char_use.shot_id IS NULL
    AND 1 = 1

    Этот запрос не будет даже предпринимать попытки вставить неуникальную запись.
    Ответ написан
  • Как сортировать внутри GROUP BY?

    FloppyFormator
    @FloppyFormator
    Ваш запрос вообще не соответствует SQL-стандарту, и то, что он работает, особенность реализации MySQL.
    Всё, что находится за пределами агрегатных функций, должно быть в GROUP BY.

    Задачу можно решить через подзапрос, self-join или кастомную агрегатную функцию наподобие ARGMAX.
    Ответ написан