PostgreSQL-как я могу заменить нулевые значения значениями из другого столбца на основе общего уникального идентификатора в представлении PSQL



У меня есть три внешних идентификатора в моем представлении PSQL. Как я могу заменить нулевые значения second_id на значения third_id, основанные на их общем first_id?



В настоящее время:





first_id | second_id | third_id
----------+-----------+----------
1 | | 11
1 | | 11
1 | | 11
1 | 22 | 22
2 | 33 | 33
3 | 44 | 44
4 | 55 | 55
5 | 66 | 66
6 | | 77
6 | | 77
6 | | 77
6 | | 77
6 | 88 | 88



Должно быть:





first_id | second_id | third_id
----------+-----------+----------
1 | 22 | 11
1 | 22 | 11
1 | 22 | 11
1 | 22 | 22
2 | 33 | 33
3 | 44 | 44
4 | 55 | 55
5 | 66 | 66
6 | 88 | 77
6 | 88 | 77
6 | 88 | 77
6 | 88 | 77
6 | 88 | 88



Как я могу это изменить?




  • нулевые значения в столбце second_id должны быть заполнены, то есть не должно быть пустых ячеек.

  • Если столбец second_id разделяет значение с столбцом third_id, это значение должно заполнить пустые ячейки в столбец second_id.

  • они оба должны быть основаны на их общем first_id.



  • Большое спасибо. Я действительно ценю это.





    second_id На самом деле является CASE WHEN модификацией third_id. Это изменение сделано в представлении.



    Вид:




        View "public.my_view"
    Column | Type | Modifiers | Storage | Description
    -----------------------------+-----------------------------+-----------+----------+-------------
    row_number | bigint | | plain |
    first_id | integer | | plain |
    second_id | integer | | plain |
    third_id | integer | | plain |
    first_type | character varying(255) | | extended |
    date_1 | timestamp without time zone | | plain |
    date_2 | timestamp without time zone | | plain |
    date_3 | timestamp without time zone | | plain |
    View definition:
    SELECT row_number() OVER (PARTITION BY t.first_id) AS row_number,
    t.first_id,
    CASE
    WHEN t.localization_key::text = 'rq.bkd'::text THEN t.third_id
    ELSE NULL::integer
    END AS second_id,
    t.third_id,
    t.first_type,
    CASE
    WHEN t.localization_key::text = 'rq.bkd'::text THEN t.created_at
    ELSE NULL::timestamp without time zone
    END AS date_1,
    CASE
    WHEN t.localization_key::text = 'st.appt'::text THEN t.created_at
    ELSE NULL::timestamp without time zone
    END AS date_2,
    CASE
    WHEN t.localization_key::text = 'st.eta'::text THEN t.created_at
    ELSE NULL::timestamp without time zone
    END AS date_3
    FROM my_table t
    WHERE (t.localization_key::text = 'rq.bkd'::text OR t.localization_key::text = 'st.appt'::text OR t.localization_key::text = 'st.eta'::text) AND t.first_type::text = 'thing'::text
    ORDER BY t.created_at DESC;





    Вот ссылка на определение таблицы, которое использует представление (my_table).



    Https://gist.github.com/dankreiger/376f6545a0acff19536d



    Еще раз спасибо за вашу помощь.

    613   2  

    2 ответов:

    Вы не можете UPDATE нижележащую таблицу my_table, потому что в ней нет столбца second_id, поэтому вы должны заставить представление отображать данные так, как вы хотите. Это довольно просто с CTE:

    CREATE VIEW my_view AS
      WITH second (first, id) AS (
        SELECT first_id, third_id
        FROM my_table
        WHERE t.localization_key = 'rq.bkd')
      SELECT
        row_number() OVER (PARTITION BY t.first_id) AS row_number,
        t.first_id,
        s.id AS second_id,
        t.third_id,
        t.first_type,
        CASE
          WHEN t.localization_key = 'rq.bkd' THEN t.created_at
        END AS date_1,
        CASE
          WHEN t.localization_key = 'st.appt' THEN t.created_at
        END AS date_2,
        CASE
          WHEN t.localization_key = 'st.eta' THEN t.created_at
        END AS date_3
      FROM my_table t
      JOIN second s ON s.first = t.first_id
      WHERE (t.localization_key = 'rq.bkd'
         OR t.localization_key = 'st.appt'
         OR t.localization_key = 'st.eta')
        AND t.first_type = 'thing'
      ORDER BY t.created_at DESC;
    

    Это предполагает, что где my_table.localization_key = 'rq.bkd' у вас есть ровно 1 third_id значение; если нет, вы должны добавить соответствующие квалификаторы, такие как ORDER BY first_id ASC NULLS LAST LIMIT 1 или какой-либо другой подходящий фильтр. Также обратите внимание, что CTE является JOINed, а не LEFT JOINed, предполагая, что всегда существует допустимая пара (first_id, third_id) Без NULLs.

    Вы можете получить его по:

    select a.first_id, coalesce(a.second_id,b.second_id), a.third_id 
    from my_table a 
    left outer join
        (
        select first_id, second_id from my_table
        where second_id is not null 
        ) b
        using (first_id)
    

    Поэтому обновление должно быть:

    update my_table a set second_id = b.second_id
      from 
      (
      select first_id, second_id from my_table 
      where second_id is not null 
      ) b
    where b.first_id = a.first_id and a.second_id is null
    

    Comments

      Ничего не найдено.