mySql - обновление путем сравнения строк в одной таблице

0

Я хочу обновить столбец, сравнивая каждую строку со всеми другими строками в таблице, но я не могу определить, как отличать имена столбцов в строке, обновляемой с помощью строк, которые просматриваются.

Здесь упрощенный пример...

люди:
  +--------+-----+----------------+
  | name | age | nameClosestAge |
  +--------+-----+----------------+
  | alice | 20 | |
  | bob | 30 | |
  | clive | 22 | |
  | duncan | 24 | |
  +--------+-----+----------------+

Чтобы заполнить столбец 'nameClosestAge' с именем человека, который ближе всего по возрасту к каждому человеку, вы можете сделать это...

create temporary table peopleTemp like people;
insert into peopleTemp select * from people;
update people set nameClosestAge = 
(select name from peopleTemp where people.name != peopleTemp.name 
order by abs(people.age - peopleTemp.age) asc limit 1);

Что производит это....
+--------+-----+----------------+
| name | age | nameClosestAge |
+--------+-----+----------------+
| alice | 20 | clive |
| bob | 30 | duncan |
| clive | 22 | alice |
| duncan | 25 | clive |
+--------+-----+----------------+

Конечно, есть способ сделать это, не создавая дублируемую таблицу. Я ищу наиболее эффективный метод здесь, так как у меня очень большая таблица и ее слишком много времени для обновления. Я использую mySql с PHP.

  • 0
    В действительности нет смысла хранить nameClosestAge (если это не для целей кэширования), так как это создает избыточность ...
  • 0
    Джаспер. Это упрощенный пример. Расчет для обновленного поля является более сложным для реальной задачи.
Показать ещё 1 комментарий
Теги:
compare

1 ответ

1

Вы можете выполнить это только с одним подзапросом и без временной таблицы.

SELECT name, age, (
  SELECT name
  FROM people
  WHERE name != ppl.name
  ORDER BY ABS( people.age - ppl.age ) 
  LIMIT 1
  ) AS nameClosestAge
FROM people AS ppl;

Проверено и работает:)

EDIT: если вы хотите работать с вычисленной строкой, вы можете использовать представление;

CREATE VIEW people_close AS 
  SELECT name, age, (
    SELECT name
    FROM people
    WHERE name != ppl.name
    ORDER BY ABS( people.age - ppl.age ) 
    LIMIT 1
  ) AS nameClosestAge
  FROM people AS ppl;

Вы не можете обновить вычисленное поле, но можете легко запросить его.

  • 0
    Спасибо Фаралия. Однако я не могу понять из вашего решения, как сделать обновление. Т.е. это не работает ... обновить людей КАК ppl set nameClosestAge = (ВЫБЕРИТЕ имя ИЗ людей, ГДЕ имя! = Ppl.name ЗАКАЗАТЬ АБС (people.age - ppl.age) LIMIT 1)
  • 0
    Хорошо .. это позор Вы не можете использовать таблицу, которую вы обновляете, в подзапросе. Работает с исходной временной таблицей, хотя и с использованием этого, но это побеждает объект вопроса ... create temporary table peopleTemp like people; insert into peopleTemp select * from people; UPDATE people SET closest = (SELECT name FROM peopleTemp WHERE people.name != peopleTemp.name ORDER BY ABS( people.age - peopleTemp.age ) LIMIT 1); Другой способ сделать это - создать представление с включенным столбцом nameClosestAge.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню