PostgreSQL,将一个表中的多个记录分配给另一个表中的单个记录

PostgreSQL,将一个表中的多个记录分配给另一个表中的单个记录,sql,postgresql,Sql,Postgresql,我在PostgreSQL中有两个表。一张有捐款的桌子和一张有特色的桌子。我想为每个功能分配一个捐赠id,但是一些捐赠id应该根据捐赠表中的数量分配给表中具有功能的多个记录 例如:有人捐赠了10个,那么对于每2个,应该为该特定捐赠分配一个特征\u id=特征表中具有相同捐赠\u id的5个记录 我正在寻找一个更新语句,因为这些特性已经存在,并且它们都有唯一的值。哪项功能分配给哪项捐赠并不重要,重要的是数量 捐款: donation_id | ammount ====================

我在PostgreSQL中有两个表。一张有捐款的桌子和一张有特色的桌子。我想为每个功能分配一个捐赠id,但是一些捐赠id应该根据捐赠表中的数量分配给表中具有功能的多个记录

例如:有人捐赠了10个,那么对于每2个,应该为该特定捐赠分配一个特征\u id=特征表中具有相同捐赠\u id的5个记录

我正在寻找一个更新语句,因为这些特性已经存在,并且它们都有唯一的值。哪项功能分配给哪项捐赠并不重要,重要的是数量

捐款:

donation_id | ammount
=====================
001         | 10
002         | 4
特点:

feature_id  | donation_id | owned
=================================
001         | 000         | false
002         | 000         | false
003         | 000         | false
004         | 000         | false
005         | 000         | false
006         | 000         | false
007         | 000         | false
008         | 000         | false
输出:

feature_id  | donation_id | owned
=================================
001         | 001         | true
002         | 001         | true
003         | 001         | true
004         | 001         | true
005         | 001         | true
006         | 002         | true
007         | 002         | true
008         | 000         | false
您可以使用一个临时表(或两个临时表,或一些子查询和冗余),玩一些小把戏:

  • 可以将a(即笛卡尔乘积)与a一起使用,以获得重复的行。[我们添加了一个row_number()列,以便能够区分它们。]
  • 您可以通过使用
    feature\u id
    s选择一定数量的特征,并使用表达式选择行数。同样,我们添加了一个row_number()列来区分它们
  • 因此,下面的代码实现了这一点:

    -- Get a (virtual) table with "donation_id" repeated as many times 
    -- as (amount/2). Trick: use a CROSS JOIN with generate_series
    WITH new_features AS
    (
        SELECT
             donation_id, row_number()  over () AS rn
        FROM
            donations 
            CROSS JOIN generate_series(1, amount/2) AS g(i)
    ),
    -- Right now we know how many rows we want to UPDATE. 
    -- The next SELECT chooses them. Trick: computed LIMIT
    to_update AS
    (
        SELECT
            feature_id, row_number() over () AS rn
        FROM
            features
        WHERE
            NOT owned
        ORDER BY
            feature_id  -- This is arbitrary, it could even not be sorted.
        LIMIT
            (SELECT count(*) FROM new_features)
    )
    -- ... and finally
    UPDATE
        features
    SET
        donation_id = new_features.donation_id, owned = true
    FROM
        to_update
        JOIN new_features USING(rn)
    WHERE
        features.feature_id = to_update.feature_id 
    RETURNING
        features.feature_id, features.donation_id, features.owned ;
    
    你可以在


    注:

    • 我假设
      feature\u id
      是主键(或备用键:unique和notnull)。如果这不是真的,则需要适当的PK
    • 与其使用
      owned
      列,还可以只使用
      捐赠id
      ,当
      NULL
      表示
      未拥有
      。这将保存一列,而不必更新该列

    请回答您的问题,并添加一些示例数据和基于该数据的预期输出。请问,如果捐款不是2的倍数怎么办?如果没有足够的功能来接收捐赠,该怎么办?如果捐赠不是2的倍数,则应四舍五入。将有足够的功能。有任何答案适合您吗?