簡體   English   中英

PostgreSQL - 更新復合類型數組的一個元素

[英]PostgreSQL - UPDATE one element of a composite type array

我有一個 PostgreSQL 表,其定義如下。

    """ 

    CREATE TYPE similarity AS (

    user_id          integer,
    similarity       real,
    rank             integer
    )
    """,
    """
    CREATE TABLE user_similarities (

    user_id      int REFERENCES books_user_id (user_id) ON UPDATE CASCADE ON DELETE CASCADE,
    similarities similarity[]
    )
    """

這是我用於測試的示例:

在此處輸入圖片說明

我想要實現的是更新數組中我的復合類型(相似性)的一個元素。 一個例子是將相似度更改為給定的值,比如說 1,user_id = 3 和 Similarities.user_id = 10。

通過以下查詢,我可以選擇 user_id = 3 和 Similarities.similarity = 10,但我不知道如何更新我的表。

sql = """with list_1 as (SELECT *, unnest(similarities) as list_similarities FROM user_similarities WHERE user_id = 3), id_1 
    as (SELECT * FROM list_1 WHERE(list_1.list_similarities).user_id=10 ) SELECT * FROM id_1"""

我嘗試了以下方法:

with list_1 as (SELECT *, unnest(similarities) as list_similarities FROM user_similarities WHERE user_id = 3), 
id_1 as (SELECT * FROM list_1 WHERE(list_1.list_similarities).user_id=10 ) UPDATE id_1 SET 
list_similarities.similarity = 1 

但我收到錯誤消息:關系“id_1”不存在第 2 行:...ERE(list_1.list_similarities).user_id=10 ) UPDATE id_1 SET l...

這是整個功能:

def update_similarity(connection,id_ ):

sql = """with list_1 as (SELECT *, unnest(similarities) as list_similarities FROM user_similarities WHERE user_id = 3), id_1 
as (SELECT * FROM list_1 WHERE(list_1.list_similarities).user_id=10 ) UPDATE id_1 SET list_similarities.similarity = 1 """

to_insert = (id_,)
bol = 0
try:
    conn = connection
    # create a new cursor
    cur = conn.cursor()
    # execute the INSERT statement
    cur.execute(sql, to_insert)
    request = cur.fetchall()
    if len(request) > 0:
        bol = 1
    cur.close()
except (Exception, psycopg2.DatabaseError) as error:
    print(error)

return bol

任何幫助,將不勝感激。

如果我沒有理解錯,你已經知道了user_idsimilarity.user_id您要更新similarity.similarity值。 我假設您也知道要更新它的值,並且它不打算作為此查詢的一部分進行計算。

考慮到這一點,這就是您可以實現的方式。

設置,基於您的示例數據:

CREATE TYPE similarity AS (
    user_id          integer,
    similarity       real,
    rank             integer
);

CREATE TABLE user_similarities (
    id           int,
    user_id      int,
    similarities similarity[]
);

INSERT INTO user_similarities
VALUES
(0, 3, '{"(10,0.66,)","(7,0.111,)"}'),
(1, 2, '{"(3,0.256,)","(7,0.891,)"}');

詢問:

UPDATE user_similarities
SET similarities = (
  SELECT ARRAY_AGG(ROW(
    s.user_id,
    CASE s.user_id WHEN 10 THEN 0.25 ELSE s.similarity END,
    s.rank
  )::similarity)
  FROM UNNEST(similarities) s
)
WHERE user_id = 3
AND 10 IN (SELECT (UNNEST(similarities)).user_id);

來自該表的SELECT *結果:

| id  | user_id | similarities                |
| --- | ------- | --------------------------- |
| 0   | 3       | {"(10,0.25,)","(7,0.111,)"} |
| 1   | 2       | {"(3,0.256,)","(7,0.891,)"} |

數據庫小提琴


基本上,要找到要更新的行很容易,您只需檢查user_id = 3 ,然后取消嵌套數組並檢查是否有任何數組元素的user_id值為 10。

更新數組內容有點不那么簡單。 我在那里做的是:

  1. 取消嵌套數組,以便我可以一次處理每個項目
  2. 即時重新創建這些復合類型(ROW,指定 3 個字段,轉換為您的類型),但是如果我找到user_id為 10 的那些,我將similarity值設置為 0.25,否則保留原始值。
  3. 將復合類型聚合回數組

這不會(或至少不一定)做的一件事是保留數組中元素的原始順序。 如果這對你很重要,它可以做到,但更痛苦。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM