Я хочу обновить столбец, сравнивая каждую строку со всеми другими строками в таблице, но я не могу определить, как отличать имена столбцов в строке, обновляемой с помощью строк, которые просматриваются.
Здесь упрощенный пример...
люди:
+--------+-----+----------------+
| 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.
Вы можете выполнить это только с одним подзапросом и без временной таблицы.
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;
Вы не можете обновить вычисленное поле, но можете легко запросить его.
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.