sql - 根据foreign_key值更新每行中的值

标签 sql postgresql

下载表:

id (primary key)
user_id
item_id
created_at
updated_at

本例中的 user_id 和 item_id 都不正确,但是,它们分别正确存储在 users 和 items 表中(每个表中都有 import_id)。这是我正在尝试编写的脚本:

downloads.each do |download|
    user = User.find_by_import_id(download.user_id)
    item = item.find_by_import_id(download.item_id)

   if user && item
    download.update_attributes(:user_id => user.id, :item.id => item.id)
   end
end

所以,

  1. 根据以下内容查找用户和项目 他们各自的“import_id”。然后
  2. 更新下载记录中的这些值

对于大量的行来说,这需要很长时间。无论如何要在 SQL 中执行此操作吗?

最佳答案

如果我理解正确的话,您只需在 SELECT 语句中添加两个子查询即可查找正确的 ID。例如:

SELECT id, 
   (SELECT correct_id FROM User WHERE import_id=user_id) AS UserID,
   (SELECT correct_id FROM Item WHERE import_id=item_id) AS ItemID,
   created_at,
   updated_at
FROM Downloads

这会将您不正确的 user_ids 转换为您想要从 User 表中获得的任何 ID,并且会对您的 item_ids 执行相同的操作。来自 SQL 的信息现在将是正确的。

但是,如果您想使用正确的信息更新表,您可以像这样编写:

UPDATE Downloads
SET user_id = User.user_id,
    item_id = Item.item_id
FROM Downloads
INNER JOIN User ON Downloads.user_id = User.import_id
INNER JOIN Item ON Downloads.item_id = Item.import_id
WHERE ...

确保在 WHERE 子句中添加一些内容,这样就不会更新“下载”表中的每条记录(除非计划如此)。我重写了上面的语句,使其更加优化,因为原始版本每行有两个 SELECT 语句,这有点密集。

编辑: 由于这是 PostgreSQL,因此您不能在 UPDATEFROM 部分中同时包含表名称。相反,FROM 部分中的表会连接到正在更新的表。以下是 PostgreSQL 网站上对此的引用:

When a FROM clause is present, what essentially happens is that the target table is joined to the tables mentioned in the fromlist, and each output row of the join represents an update operation for the target table. When using FROM you should ensure that the join produces at most one output row for each row to be modified. In other words, a target row shouldn't join to more than one row from the other table(s). If it does, then only one of the join rows will be used to update the target row, but which one will be used is not readily predictable.

http://www.postgresql.org/docs/8.1/static/sql-update.html

考虑到这一点,这是一个我认为应该有效的示例(无法测试,抱歉):

UPDATE Downloads
SET user_id = User.user_id,
    item_id = Item.item_id
FROM User, Item 
WHERE Downloads.user_id = User.import_id AND
      Downloads.item_id = Item.import_id

这就是基本思想。不要忘记您仍然需要向 WHERE 部分添加额外的条件来限制更新的行。

关于sql - 根据foreign_key值更新每行中的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6003049/

相关文章:

mysql - 如何获取所有行以及列名作为第一行

sql - 使用 PL/SQL 将值插入全局临时表

sql - 3000 万条记录。将它们分成 24 小时的时间段。一个月的总和。冲洗并重复

MySQL 计算上一年客户的订单数量

regex - 为 Redshift 重复正则表达式

Postgresql 增量如果存在或创建一个新行

json - Postgres : expand JSON array elements into values with their index?

java - 在 JAVA 中使用 session 用户的 MYSQL 查询

postgresql - Postgres 提交是否可以存在于具有异常 block 的过程中?

postgresql - 花费很长时间的批量/多个查询在 Postgres 中永远不会完成