Rails (или, может быть, SQL): поиск и удаление дублированных объектов AR - PullRequest
0 голосов
/ 13 апреля 2009

Объекты ActiveRecord класса 'Location' (представляющие местоположения таблицы db) имеют атрибуты url, lat (широта) и lng (долгота).

Lat-lng-комбинации на этой модели должны быть уникальными. Проблема в том, что в базе данных много объектов Location, имеющих дублирующие комбинации lat-lng.

Мне нужна помощь в выполнении следующих действий

  1. Найти объекты с одинаковыми LAT-LNG-комбинация.
  2. Если атрибут 'url' объекта не пусто, сохраните этот объект и удалите другие дубликаты. В противном случае просто выберите самый старый объект (проверяя атрибут 'create_at') и удалите другие дубликаты.

Поскольку это однократная операция, также приветствуются решения на SQL (совместимые с MySQL 5.1).

Ответы [ 2 ]

5 голосов
/ 13 апреля 2009

Если это одноразовая вещь, то я просто делаю это в Ruby и не слишком беспокоюсь об эффективности. Я не проверил это полностью, проверил сортировку и тому подобное, чтобы убедиться, что она будет делать именно то, что вы хотите, прежде чем запускать это на своей базе данных:)

keep = []
locations = Location.find(:all)

locations.each do |loc|
  # get all Locations's with the same coords as this one
  same_coords = locations.select { |l| l.lat == loc.lat and \
                                       l.lng == loc.lng }
  with_urls = same_coords.select { |l| !l.url.empty? }

  # decide which list to use depending if there were any urls
  same_coords = with_urls.any? ? with_urls : same_coords

  # pick the best one
  keep << same_coords.sort { |a,b| b.created_at <=> a.created_at }.first.id
end

# only keep unique ids
keep.uniq!

# now we just delete all the rows we didn't decide to keep
locations.each do |loc|
  loc.destroy unless keep.include?( loc.id )
end

Теперь, как я уже сказал, это определенно плохой, плохой код. Но иногда просто взломать то, что работает, стоит потраченного времени на то, чтобы придумать что-то «лучше», особенно если это разовое.

0 голосов
/ 13 апреля 2009

Если у вас есть 2 столбца MySQL, вы можете использовать функцию CONCAT.

SELECT * FROM table1 GROUP BY CONCAT(column_lat, column_lng)

Если вам нужно знать общую сумму

SELECT COUNT(*) AS total FROM table1 GROUP BY CONCAT(column_lat, column_lng)

Или вы можете комбинировать оба

SELECT COUNT(*) AS total, table1.* FROM table1 
GROUP BY CONCAT(column_lat, column_lng)

Но если вы сможете объяснить больше по вашему вопросу, возможно, у нас будут более актуальные ответы.

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