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

    @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 остальные две таблицы.
    Ответ написан
    1 комментарий
  • Как заменить строку на цифры у оператора 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;
    Ответ написан
    Комментировать
  • Как в PosgreSQL, в JSON добавить key:value?

    @Akina
    Сетевой и системный админ, SQL-программист.
    https://www.postgresql.org/docs/current/functions-...

    Оператор конкатенации JSONB - ||

    В более сложных случаях - jsonb_set(), jsonb_insert()... в общем, посмотри сам.
    Ответ написан
    Комментировать
  • Как правильно конвертировать SQL дату, чтобы корректно принять и отправить?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Хранить следует в формате для хранения даты (с учётом необходимости дополнительного хранения информации о зоне времени). Если СУБД имеет встроенный тип DATE - следует использовать его. Если такого нет - DATETIME. Если и такого нет - TIMESTAMP.

    Вводить следует в том формате, в каком согласно документации следует представлять литералы даты.
    Ответ написан
    Комментировать
  • Как выбрать дату последней транзакции (чтоб эта транзакция была 7 дней назад)?

    @Akina
    Сетевой и системный админ, SQL-программист.
    SELECT id AS servie_id,
           name AS servie_name,
           MAX(TO_TIMESTAMP(created_at))::DATE AS last_trans_date
    FROM services
    GROUP BY 1,2
    HAVING last_trans_date <= CURRENT_DATE - INTERVAL '7 day'
    Ответ написан
    Комментировать
  • Где ошибка в EXECUTE FORMAT?

    @Akina
    Сетевой и системный админ, SQL-программист.
    CREATE OR REPLACE FUNCTION _Foo2(st TIMESTAMP, fin TIMESTAMP)
    RETURNS TABLE (out_key INTEGER, out_tst timestamptz, out_val FLOAT) AS $$
    DECLARE  
      
    BEGIN
    
      RETURN QUERY EXECUTE FORMAT('
      SELECT %I, %I, %I
      FROM %I 
      WHERE %I BETWEEN ''%s'' AND ''%s'';
      ', 
      'in_key', 'in_tst', 'in_val', 'in_table', 'in_tst', st, fin);
    
    END;
    
    $$ LANGUAGE plpgsql;


    DEMO fiddle

    Ошибки найдёте самостоятельно...
    Ответ написан
    1 комментарий
  • Как заставить работать COUNT с GROUP BY?

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

    Вариантов несколько.

    Первый, наиболее правильный - получить это значение отдельным запросом.
    SELECT COUNT(*)  AS cnt
    FROM (
        SELECT 1
        FROM "order" AS o
             LEFT JOIN product p ON (p.order_id = o.id)
        GROUP BY o.id
        HAVING sum(p.price) >= 10
    ) x


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

    Третий - добавить соотв. поле в каждую запись выходного набора, используя оконную функцию, и взять значение из любой записи:
    SELECT o.id, COUNT(o.id) OVER () AS cnt
    FROM "order" AS o
             LEFT JOIN product p ON (p.order_id = o.id)
    GROUP BY o.id
    HAVING sum(p.price) >= 10
    Ответ написан
  • Агрегирование в контексте группы и оконной функции?

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

    Именно так и будет. Считай, что оконные функции работают после HAVING и перед ORDER BY.
    Ответ написан
    Комментировать
  • Как получить всю БД в виде csv?

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

    Например, под термином CSV можно понимать как файл единой структуры (причём как plain-структуры, так и с сериализованными данными), так и несколько конкатенированных (как в процессе вывода, так и явно по окончании вывода) файлов, каждый из которых имеет свою структуру (да ещё и дополнительная информация там может храниться, вроде имён таблиц и имён/типов полей).

    Каждый из вариантов предполагает свой код для решения задачи (это если не обращать внимания на такую мелочь, что сама по себе запись в CSV в каждой СУБД делается тоже ну очень по-своему).

    А так - вот не вижу ну никакой проблемы. Лишь бы на той стороне обработки этого CSV был код, который правильно интерпретирует данные и корректно разложит их обратно по таблицам. Причём если идёт речь о создании универсального инструмента, то только в этом самом последнем моменте (вывод результата запроса в CSV) могут возникнуть хоть какие-то сложности. Остальное просто и плоско, как блин.

    Я не знаю их архитектуру и название таблиц заранее

    Хотя вот ещё одна точка, где могут возникнуть сложности. Теоретически все СУБД должны бы поддерживать INFORMATION_SCHEMA, всё же стандарт как бы описывает - и всё равно не всё там просто и очевидно.
    Ответ написан
    2 комментария