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

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT *
    FROM table
    ORDER BY user_id = @user_id DESC, id DESC LIMIT 1

    Если заданный @user_id есть - вернётся соотв. запись. Если таких записей несколько - вернётся запись из них с максимальным id. Иначе вернётся просто запись с макс. id.

    Если же под "Если есть user_id вернуть запись с user_id" разумеется "ну хоть какой-то, лишь бы не NULL", то
    SELECT *
    FROM table
    ORDER BY user_id IS NULL, id DESC LIMIT 1
    Ответ написан
    Комментировать
  • Как вывести элемент, если нет связи many to many?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Шаблон при решении такого рода задач следующий:
    SELECT *
    FROM products 
    CROSS JOIN categories
    LEFT JOIN products_category USING (product_id, category_id)

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

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT t1.*, t2.category_id AS main_category_id
    FROM table t1
    JOIN table t2 USING (product_id)
    WHERE {условия по таблице t1, определяющие нужный продукт}
      AND t2.main_category
    Ответ написан
    2 комментария
  • Как прибавить к текущей дате дни?

    @Akina
    Сетевой и системный админ, SQL-программист.
    В случае MySQL просто прибавить соотв. INTERVAL:
    INSERT INTO `order`
    SET ...
        date_end = CURRENT_DATE + INTERVAL :days_to_add DAY

    В других СУБД - использовать функцию DATEADD().
    Ответ написан
    Комментировать
  • Как запустить OPTIMIZE_TABLE через shell скрипт для конкретных БД?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Создайте хранимую процедуру, которая принимает имя БД и выполняет нужную команду для каждой таблицы базы. И выполняйте её.
    Ответ написан
    Комментировать
  • Правда ли что логический порядок выполнения запроса может не совпадать с планировщиком?

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

    А вот с планом он совпадает на 100% - ну просто потому что выполняется именно по этому плану.
    Ответ написан
    Комментировать
  • Как правильно создать запрос?

    @Akina
    Сетевой и системный админ, SQL-программист.
    DELETE t1 
    FROM review_detail t1
    JOIN review_detail t2 USING (title, nickname)
    WHERE t1.detail_id < t2.detail_id;

    https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=dc6a90...
    Ответ написан
    2 комментария
  • Почему выдает ошибку literal does not match format string при добавлении даты?

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

    Используй явное форматирование:
    INSERT INTO people (last_name, first_name, sex, birthday)
    VALUES ('Иванов', 'Иван', 'm', TO_DATE('1999-04-04', 'YYYY-MM-DD'));


    DEMO
    Ответ написан
    Комментировать
  • Как получить первое non-NULL значение в группе для данного поля?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT DISTINCT 
           client_id,
           FIRST_VALUE(massage) 
               OVER (PARTITION BY client_id 
                     ORDER BY massage IS NULL, dttm) massage
    FROM test

    Если СУБД не поддерживает прямого ORDER BY massage IS NULL, dttm, то ORDER BY CASE WHEN massage IS NULL THEN 1 ELSE 0 END, dttm.

    https://dbfiddle.uk/?rdbms=mysql_8.0&rdbms2=sqlser...
    Ответ написан
    Комментировать
  • Как посчитать общую длительность времени между строками определенной выборки в MySQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH cte AS ( SELECT *, 
                         LAG(`datetime`) OVER (PARTITION BY login ORDER BY `datetime`) lag_datetime, 
                         LAG(event) OVER (PARTITION BY login ORDER BY `datetime`) lag_event 
                  FROM history )
    SELECT login, SUM(TIMESTAMPDIFF(MINUTE, lag_datetime, `datetime`)) duration
    FROM cte
    WHERE (event, lag_event) = (2,1)
    GROUP BY login;

    https://dbfiddle.uk/?rdbms=mariadb_10.6&fiddle=398... (исходные данные подправлены).
    Ответ написан
    1 комментарий
  • Как создать свою двойную шапку заголовков в запросе?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT {выходные поля запроса}
    FROM ( SELECT 3 AS rownumber, {выходные поля запроса}
           FROM {остальное тело запроса} )
         UNION ALL
         ( SELECT 1, {надписи шапки}
           FROM DUAL )
         UNION ALL
         ( SELECT 2, {кастомные названия}
           FROM DUAL )
    ) AS total
    ORDER BY rownumber, {остальные поля сортировки};
    Ответ написан
  • Как добавить свойство в каждый элемент массива в postgresql /jsonb при помощи sql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH cte AS (
        SELECT 'Bob' AS name, 25 AS age UNION ALL
        SELECT 'Mark'       , 30        UNION ALL
        SELECT 'Joe'        , 35
    )
    SELECT test.id,
           jsonb_build_object('items', jsonb_agg(jae.value_1 || jsonb_build_object('age', cte.age)))
    FROM test
    CROSS JOIN jsonb_array_elements(test.value->'items') AS jae (value_1)
    LEFT JOIN cte ON cte.name = jae.value_1->>'name'
    GROUP BY test.id

    DEMO
    Ответ написан
    2 комментария
  • Как ограничить количество через join?

    @Akina
    Сетевой и системный админ, SQL-программист.
    хотелось бы посмотреть на версию mysql 5.7


    Ну например так:
    SELECT department.name as department_name, 
           employee.name
    FROM employee 
    JOIN department ON employee.department_id = department.id 
    WHERE 2 > ( SELECT COUNT(*)
                FROM employee emp
                WHERE emp.department_id = employee.department_id
                  AND emp.id < employee.id )

    Ну или так:
    SELECT department.name as department_name, 
           subquery.name
    FROM department
    JOIN ( SELECT employee.*,
                  @row_number := CASE WHEN @department = department_id
                                      THEN @row_number + 1
                                      ELSE 1
                                      END rownumber,
                  @department := department_id
           FROM employee
           CROSS JOIN ( SELECT @department:=0, @row_number:=0 ) variables
           ORDER BY department_id, id ) subquery ON subquery.department_id = department.id
    WHERE subquery.rownumber <= 2


    fiddle
    Ответ написан
    Комментировать
  • Как в select добавить нумерацию результатов?

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

    Обломись.

    В таблице нет никакого порядка, таблица - это несортированная куча. Тот порядок, в котором записи вставлялись в таблицу, не более чем временная видимость. И тот порядок, который выдаётся сейчас, запросто имеет полное право измениться завтра. И обязательно изменится - причём по закону великой подлости в самый неудобный для тебя момент.

    Сортировка - это не выпендрёж, а осознанная необходимость, Единственный способ получить детерминированный результат.
    Ответ написан
    Комментировать
  • Как объединить 2 запроса в 1 в Postgresql или как изменить запрос ниже?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Чисто технически, без понимания сути происходящего:
    WITH cte AS (
        SELECT PIP.purchase_id, SUM(PIP.product_count * PR.new_price) AS all_sum
        FROM product_in_purchase AS PIP
        RIGHT OUTER JOIN price_register AS PR ON PIP.product_id = PR.product_id
        GROUP BY PIP.purchase_id
    )
    ( SELECT * FROM cte ORDER BY all_sum ASC LIMIT 1 )
    UNION 
    ( SELECT * FROM cte ORDER BY all_sum DESC LIMIT 1 )
    Ответ написан
    4 комментария
  • Как добавить в пустой столбец таблицы сумму из другой таблицы по заданному условию?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Подскажите пожалуйста, какую функцию необходимо написать, чтобы в column_3 подсчитывалась сумма из column_2 учитывая группировку с column_1?

    Прежде чем спрашивать "как", обоснуйте, зачем это делать.

    Хранение агрегированной суммы в таблице - это называется "переопределённые данные". Что (1) практически никогда не нужно (2) зачастую просто вредно. Правильно - считать требуемое значение из исходных данных в тот момент, когда оно реально нужно.

    Хранение переопределённых данных - это просто хранение лишнего. Но это не единственная опасность. Любая нештатная ситуация - и значение запросто может не обновиться, либо неверно обновиться. Итогом станет хранение в таблице неправильных значений. И что самое противное - эта неправильность ну никак не детектируется. Пока наконец использование неверного значения не аукнется где-то в другом месте, с фейерверком и воплями, а то и с увольнением программиста, допустившего такой архитектурный косяк.
    Ответ написан
    Комментировать
  • Где может быть ошибка в SQL запросе?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Причина очень проста. Формально comma-style join - это алиас CROSS JOIN. Но есть подвох - приоритет comma-style join ниже приоритета explicit join. И выражение источника данных, если расставить скобки в соответствии с приоритетом, получится такое:

    from
    table1 , ( table2
               left join table1 h on table1.id = h.id
               left join table2 s on table2.id = s.id )

    Вот теперь прекрасно видно, что внутри скобки о существовании где-то там снаружи table1 ничего не известно.

    Правильно - забыть НАВСЕГДА о возможности использовать запятую. И писать вот так:
    FROM table1 
    CROSS JOIN table2
    LEFT JOIN table1 h ON table1.id = h.id
    LEFT JOIN table2 s ON table2.id = s.id


    PS. Если всё же без comma-style жизнь не мила, можно поступить так, как обычно делают для явного задания приоритета. То есть добавить задающие приоритет скобки:
    FROM (table1 , table2)
    LEFT JOIN table1 h ON table1.id = h.id
    LEFT JOIN table2 s ON table2.id = s.id

    Теперь всё в порядке - сначала выполнится запятая, а потом к результату будут LEFT JOIN остальные две таблицы.
    Ответ написан
    Комментировать
  • Как заменить строку на цифры у оператора IN?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если передаваемый параметр - это CSV идентификаторов, то следует использовать
    SELECT *
    FROM `users`
    WHERE FIND_IN_SET(id, ?);


    Примечание 1. CSV не должен содержать никаких паразитных пробелов (а то любят всякие "украшатели" понатыкать пробелов после запятой).
    Примечание 2. Такой запрос - гарантированный фуллскан. Зато не будет инъекции.

    PS. В принципе этот CSV несложно довести до состояния JSON array (всего-то две скобки добавить) - тогда можно применить JSON_CONTAINS(), что может быть немного быстрее. А уж если переданный JSON распарсить на отдельные значения с помощью JSON_TABLE(), так ещё и от фуллскана избавимся (правда, версия сервера нужна достаточно свежая).
    Ответ написан
    2 комментария
  • Как посчитать сумму по двум столбцам в таблице, за прошлую неделю от текущей?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH cte AS (
        SELECT *, DENSE_RANK() OVER (ORDER BY period DESC) drnk
        FROM source_table
    )
    SELECT period,
           SUM(some_value) AS 'Количество order_cost', 
           SUM(just_value) AS 'Количество доставок', 
    FROM cte
    WHERE drnk = 2
    GROUP BY 1;
    Ответ написан
    Комментировать