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

    erge
    @erge
    Примус починяю
    Пытался сделать через ROW_NUMBERS() OVER (PATRITION BY date ORDER BY date, time, check), ну тут, конечно, получается он игнорит check и просто проставляет 1,2,3,4,5.


    вы же написали ниже что группировка по дате и чеку, а делаете PATRITION BY date

    Если добавить PATRITION BY date, check, то он, блин, сортирует по check потом и тоже не то выходит


    правильно, потому что необходимо группировать по тем критериям по которым необходимо и делать сортировку по негруппируемому полю по которому надо сделать счет - time

    ROW_NUMBERS() OVER (PATRITION BY date, check ORDER BY time)

    тогда он посчитает как надо.
    а уж если необходимо еще как-то отсортировать или отобрать, то заворачиваете этот запрос в подзапрос или CTE и делаете из него запрос с WHERE , ORDER и т.п. и т.д.
    Ответ написан
    Комментировать
  • Как загрузить данные в таблицу из csv в postgres с помощью python (psycopg2)?

    erge
    @erge
    Примус починяю
    Если прям вот вообще надо исключительно через скрипт и исключительно через python, то
    читаешь csv файл построчно, собираешь в массив, отправляешь batch insert в постгрис.
    см. executemany(query, vars_list)

    tuples = ((123, "foo"), (42, "bar"), (23, "baz"))
    cur.executemany("INSERT INTO test (num, data) VALUES (%s, %s)", tuples)
    Ответ написан
    Комментировать
  • Как правильно собирать данные с разных таблиц БД?

    erge
    @erge
    Примус починяю
    Для построения такого JSON на SQL вам нужны функции json_agg() / json_build_object(), далее обычные запросы с объединениями и группировкой.

    Пример как собрать JSON author
    SELECT json_build_object(
        'account_id', id,
        'first_name', first_name,
        'last_name', last_name
      ) AS author
      FROM accounts

    post собирается как
    json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )
    при объединении таблиц posts и accounts
    через json_agg собираем в массив
    SELECT json_agg(json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS posts
      FROM posts p
      JOIN accounts a ON a.id = p.author_id

    комментарии аналогично, но с группировкой по постам - post_id
    SELECT json_agg(json_build_object(
        'comment_id', c.id,
        'body', c.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS comments
      FROM comments c
      JOIN accounts a ON a.id = c.author_id
      GROUP BY post_id

    далее объединяем комментарии с постами через post_id = id
    для удобства комментарии вынес в CTE (общее табличное выражение)
    WITH cmts AS (
    SELECT json_agg(json_build_object(
        'comment_id', c.id,
        'body', c.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS comments,
      post_id
      FROM comments c
      JOIN accounts a ON a.id = c.author_id
      GROUP BY post_id
    )
    SELECT json_agg(json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        ),
        'comments', COALESCE(c.comments, '[]')
      )) AS "posts with comments"
      FROM posts p
      JOIN accounts a ON a.id = p.author_id
      LEFT JOIN cmts c ON c.post_id = p.id


    см. пример sqlfiddle
    Ответ написан
    1 комментарий
  • Как получить таблицу с верными данными и с исключениями?

    erge
    @erge
    Примус починяю
    Используйте регулярное выражение для отбора числовых значений в population
    population ~ '^[0-9]+$'

    -- Выбираем по population где только число и больше 4000
    SELECT *
      FROM planet_osm_point
      WHERE place = 'town'
        AND population ~ '^[0-9]+$'
        AND population::int > 4000
    
    -- Отбираем нечисловые значение в population и вставляем в таблицу contr_planet_osm_point
    INSERT INTO contr_planet_osm_point
    SELECT *
      FROM planet_osm_point
      WHERE place = 'town'
        AND population !~ '^[0-9]+$'


    см. пример на dbfiddle

    UPDATE:
    по комментариям, для того чтобы "железно" по порядку работало - отбор чисел-> отбор по условию.
    SELECT *
      FROM (
        SELECT *
          FROM planet_osm_point
          WHERE place = 'town'
            AND population ~ '^[0-9]+$'
      ) t
      WHERE population::int > 4000


    UPDATE2:
    да согласен, с xukapy, БД может в принципе как угодно выполнить условия в процессе оптимизации, поэтому лучше жестко задавать порядок выполнения.

    считаю можно как подзапросом выше, так и как пишут в статье - PostgreSQL Antipatterns: вычисление условий в SQL
    использовать CASE -
    WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;


    SELECT *
      FROM planet_osm_point
      WHERE place = 'town'
        AND CASE WHEN population ~ '^[0-9]+$' THEN population::int > 4000 ELSE false END
    ;
    Ответ написан
  • Почему не работает изменение таблицы?

    erge
    @erge
    Примус починяю
    Melkij , дело говорит )
    см. PostgreSQL CHECK Constraint

    ALTER TABLE persons 
       ADD CONSTRAINT persons_check_rols CHECK (rols in('registrator', 'coordinator', 'user'));
    Ответ написан
    Комментировать
  • Как изменить запрос ms sql чтобы работал на postgresql?

    erge
    @erge
    Примус починяю
    а вы доку пробовали смотреть, как добавить default value, constraint, foreign key ?

    ALTER TABLE salary ALTER COLUMN salary_date SET DEFAULT current_date;
    
    ALTER TABLE salary
    ADD CONSTRAINT FK_Salary_Employee_ID FOREIGN KEY(employee_id)
    REFERENCES EMPLOYEE(employee_id)
    ON UPDATE CASCADE
    ON DELETE CASCADE


    Таблица EMPLOYEE разумеется должна существовать, а поле employee_id должно быть уникальным.

    https://dbfiddle.uk/?rdbms=postgres_10&fiddle=238a...
    Ответ написан
    1 комментарий
  • Запрос по двум таблицам PostgresSQL?

    erge
    @erge
    Примус починяю
    SELECT id FROM (
      SELECT id FROM tbl1
      UNION
      SELECT id FROM tbl2 WHERE is_active = 1
    ) WHERE id = SOME_ID
    Ответ написан
    Комментировать
  • Как вызывать функцию по времени которое указано в базе?

    erge
    @erge
    Примус починяю
    пользователь - пользователь программы?

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

    можно конечно заморочиться и под каждую пользовательскую задачу создавать Job.
    Ответ написан
    Комментировать
  • Как отформатировать результат чтоб он был без не значащих нулей?

    erge
    @erge
    Примус починяю
    Еще так можно:
    select 
      case
        when c1 = 0 then ''
        else rtrim(to_char (c1, 'FM9999999999999999D99'), '.')
      end result
    from newtable


    см. Data Type Formatting Functions
    Ответ написан
    Комментировать
  • Как проверить массив на то, что все значения IS NULL?

    erge
    @erge
    Примус починяю
    не знаю как вы сделали объединение по своему прошлому вопросу, но надо было сначала отобрать уникальные записи из первой таблицы, а затем уже заджойнить к ней вторую таблицу и агрегировать value в массив, тогда там где во второй таблице ничего нет к первой в массиве всего лишь один элемент null, соответственно берем первый элемент массива и смотрим его на null и т.д.

    в-общем как-то так:

    SELECT
      t.a1, t.a2, t.a3,
      CASE WHEN ( ARRAY_AGG(t2.value) )[1] IS null THEN null ELSE ARRAY_AGG(t2.value) END AS arr
    FROM (
        SELECT 
          t1.a1,
          t1.a2,
          t1.a3
        FROM table1 t1
        GROUP BY t1.a1, t1.a2, t1.a3
      ) t
    LEFT JOIN table2 t2 ON t.a1 = t2.b1 AND t.a2 = t2.b2 AND t.a3 = t2.b3
    GROUP BY t.a1, t.a2, t.a3


    но если в value второй таблицы будет null и этот элемент окажется первым, то это сработает и вернет null На весь массив.
    можно было бы вставить проверку длины массива, но к сожалению по непонятным причинам функция ARRAY_LENGTH не работает (т.е. не найдена) ни у меня на pgsql 11 ни в sqlfiddle , как-то странно, а в доке пишут про нее... :??
    но есть ARRAY_DIMS и тогда запрос можно переписать так:

    SELECT
      t.a1, t.a2, t.a3,
      CASE WHEN
              (ARRAY_DIMS(ARRAY_AGG(t2.value)) = '[1:1]')
          AND ( ARRAY_AGG(t2.value) )[1] IS null
        THEN null ELSE ARRAY_AGG(t2.value)
      END AS arr
    FROM (
        SELECT 
          t1.a1,
          t1.a2,
          t1.a3
        FROM table1 t1
        GROUP BY t1.a1, t1.a2, t1.a3
      ) t
    LEFT JOIN table2 t2 ON t.a1 = t2.b1 AND t.a2 = t2.b2 AND t.a3 = t2.b3
    GROUP BY t.a1, t.a2, t.a3


    т.е. собственно ответ:
    CASE WHEN
              (ARRAY_DIMS(ARRAY_AGG(t2.value)) = '[1:1]')
          AND ( ARRAY_AGG(t2.value) )[1] IS null
        THEN null ELSE ARRAY_AGG(t2.value)
      END
    Ответ написан
  • Как написать запрос для выбора связей без дубликатов PostgreSQL?

    erge
    @erge
    Примус починяю
    SELECT 
      t2.b1,
      t2.b2,
      t2.b3,
      ARRAY_AGG(t2.value)
    FROM table2 t2
    WHERE EXISTS (
      SELECT 1
        FROM table1 t1
        WHERE t1.a1 = t2.b1
          AND t1.a2 = t2.b2
          AND t1.a3 = t2.b3
    )
    GROUP BY t2.b1, t2.b2, t2.b3


    PS:
    Подскажите пожалуйста, как в колонке array_agg получить уникальные значения (в виде массива)

    вообще-то они не уникальные и я так понимаю вопрос должен был звучать как-то типа:
    как из table2 выбрать значения по трем ключам связям с table1 и агрегировать колонку value в "массив"?
    Ответ написан
  • Каким образом конвертировать в PgSQL тип MySQL binary с его значениями?

    erge
    @erge
    Примус починяю
    Смотрите Типы данных в PostgreSQL
    в PostgreSQL это тип данных bytea - Binary Data Types
    Ответ написан
    Комментировать