Обновите значения в каждой строке на основе значения foreign_key - PullRequest
2 голосов
/ 14 мая 2011

Таблица загрузок:

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?

Ответы [ 2 ]

2 голосов
/ 14 мая 2011

Если я вас правильно понимаю, вам просто нужно добавить два подзапроса в вашем операторе SELECT для поиска правильных идентификаторов. Например:

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, и будет делать то же самое для ваших 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, вы не можете иметь имя таблицы как в разделе UPDATE, так и в разделе FROM. Вместо этого таблицы в разделе FROM объединяются с обновляемой таблицей. Вот цитата об этом с сайта PostgreSQL:

Когда присутствует предложение FROM, по существу происходит то, что целевая таблица объединяется с таблицами, упомянутыми в списке from, и каждая выходная строка объединения представляет операцию обновления для целевой таблицы. При использовании FROM вы должны убедиться, что соединение создает не более одной выходной строки для каждой строки, подлежащей изменению. Другими словами, целевая строка не должна соединяться с более чем одной строкой из других таблиц. Если это так, то только одна из строк соединения будет использоваться для обновления целевой строки, но какая из них будет использоваться, трудно предсказать.

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, чтобы ограничить количество обновляемых строк.

1 голос
/ 14 мая 2011

Я полностью догадываюсь по вашему вопросу, но у вас есть какая-то справочная таблица, которая будет соответствовать импортируемому user_id с real user_id и аналогичным образом из элементов. то есть предполагается, что ваша строка кода:

User.find_by_import_id(download.user_id)

попадает в базу данных для поиска. таблицы import_users / import_items - это просто имена, которые я дал таблицам поиска, чтобы сделать это.

UPDATE downloads
SET downloads.user_id = users.user_id
, downloads.item_id = items.items_id
FROM downloads
INNER JOIN import_users ON downloads.user_id = import_users.import_user_id
INNER JOIN import_items ON downloads.item_id = import_items.import_item_id

В любом случае (поиск выполняется в БД или он получен из кода), не проще ли было бы сначала правильно вставить информацию? это означало бы, что у вас не может быть никаких FK на вашем столе, так как иногда они указывают на один стол, а другие указывают на другой. кажется немного странным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...