2010-08-26 52 views
0

我想通過比較每行到表中的所有其他行來更新列,但我無法弄清楚如何區分被更新行中的列名與正在搜索的行通過。mySql - 通過比較同一表中的行來更新

這裏有一個簡單的例子...

人:
+--------+-----+----------------+
| 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 |
+--------+-----+----------------+

當然是有辦法做到這一點,而無需創建一個重複表。 我在這裏尋找最有效的方法,因爲我有一個非常大的表,它需要很長時間來更新。 我在PHP中使用mySql。

+0

_store_ nameClosestAge(除非是用於緩存目的),因爲它會創建冗餘...... – Jasper 2010-08-26 10:47:35

+0

Jasper真的沒什麼意義。這是一個簡單的例子。對於真正的問題,更新字段的計算更復雜。 – spiderplant0 2010-08-26 12:16:49

+0

...以後的查詢要求我搜索更新的字段。 – spiderplant0 2010-08-26 12:27:32

回答

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; 

經過和工程:)

編輯:如果你希望能夠與calc'ed行工作,你可以使用一個視圖。

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

謝謝pharalia。但是我無法從你的解決方案中找出如何更新。即這並不工作... 更新人民PPL設置nameClosestAge = (SELECT名 FROM人WHERE 名= ppl.name ORDER BY ABS(people.age - !ppl.age) LIMIT 1 ) – spiderplant0 2010-08-26 12:26:09

+0

確定。這真是一個恥辱。您不能使用您在子查詢中更新的表格。雖然使用這個工作原始臨時表,但是打敗了問題的對象... '創建臨時表peopleTemp像人; 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列的視圖。 – pharalia 2010-08-26 12:49:08