2011-05-12 31 views
9

我有一個郵政編碼表,我想用它的3個最近的鄰居更新每個郵政編碼。即填補空白此表:mySQL - 使用select返回多行更新多列

postcode nearestPostcode1 nearestPostcode2 nearestPostcode3 
_______________________________________________________________ 

KY6 1DA  -    -     - 
KY6 1DG  -    -     - 
KY6 2DT  -    -     - 
KY6 1RG  -    -     - 
.... 

我已經想通了一個SELECT查詢找到最近的郵政編碼,這裏是一個笨拙的方式,第一行可能被更新:

update table1 set 
nearestPostcode1 = (select query for returning the first nearest postcode), 
nearestPostcode2 = (select query for returning the second nearest postcode), 
nearestPostcode3 = (select query for returning the third nearest postcode) 
where postcode = 'KY6 1DA'; 

但是,這將導致爲每個行更新運行3個選擇查詢。

update table1 set 
(nearestPostcode1, nearestPostcode2, nearestPostcode3) = 
(select query to return the 3 nearest postcodes) 
where postcode = 'KY6 1DA'; 

在上面看起來「選擇查詢」類似這樣的:如果有一些方法做的是通過這個僞代碼表示這將是更有效的

select postcode from postcodeTable 
order by <equation to calculate distance> ASC 
limit 3 

反正對從select中返回的行將被放入一個可用於更新多個字段的表單中? 謝謝。

+0

「最近的郵政編碼」是如何確定的? – Thomas 2011-05-12 22:34:42

+0

@Thomas緯度和經度也存儲在郵政編碼表中,我轉換爲米和使用pythageros – spiderplant0 2011-05-12 22:45:56

回答

10
Update Table1 
    Cross Join (
       Select Min(Case When Z1.Num = 1 Then Z1.postcode End) As PostCode1 
        , Min(Case When Z1.Num = 2 Then Z1.postcode End) As PostCode2 
        , Min(Case When Z1.Num = 3 Then Z1.postcode End) As PostCode3 
       From (
         Select postcode 
          , @num := @num + 1 As Num 
         From postcodeTable 
         Where postcode = 'KY6 IDA' 
         Order By <equation to calculate distance> ASC 
         Limit 3 
         ) As Z1 
       ) As Z 
Set nearestPostCode1 = Z.PostCode1 
    , nearestPostCode2 = Z.PostCode2 
    , nearestPostCode3 = Z.PostCode3 
Where Table1.postcode = 'KY6 IDA' 
+0

謝謝@Thomas。這工作。然而,我需要擴展代碼,我無法弄清楚「Min(Case When Z1.Num = 1 Then Z1.postcode End)As PostCode1」的含義。我認爲「敏」是用於「羣」。我試圖用「IF(@ rownum = 1,postcode,''))AS PostCode1」替換它們,但我無法讓它工作。你能解釋一下「Min(Case ...)」是如何工作的 – spiderplant0 2011-05-13 13:18:45

+0

@ spiderplant0 - 通常情況下,Min與Group By一起使用,但是如果每個列都包含在一個聚合函數中(如「Z」派生表) – Thomas 2011-05-13 16:45:21

+0

@ spiderplant0 - 您應該使用'Case'而不是'If'作爲'Case'符合ANSI標準。注意,我必須在它自己的派生表(Z1)中計算順序,然後評估我的表達式像Z1.Num = 1. – Thomas 2011-05-13 16:46:59

0

我想你可以用僞代碼做到這一點:

REPLACE INTO table1 (postcode, nearestPostcode1, nearestPostcode2, nearestPostcode3) 
    SELECT "KY6 1DA", col1, col2, col3 FROM myTable WHERE ...; 

它會更容易指定它看到了真正的SQL。

注意第一列被指定爲引號中的常量。爲此,postcode必須是UNIQUEPRIMARY索引。

+0

謝謝@ james-c我應該說明我的選擇查詢返回3行而不是3列。即它會返回最接近的3個郵編。我已經添加了一些更多的原始問題來解釋這一點。 – spiderplant0 2011-05-12 22:48:34

+0

用於選擇查詢以找到3個最接近的郵政編碼實際的SQL是\t SELECT郵編FROM postcode_table \t其中 \t LAT>。 「($ LAT - $ deltaLat)」 和 \t LAT <「($ LAT + $ deltaLat) 「和 \t LNG>」($ LNG - 。。。$ deltaLng) 「和 \t LNG <」($ LNG + $ deltaLng)「和 \t活性= '1' \t ORDER BY \t POW(lat - $ lat,2)+ \t POW((lng - $ lng)* $ lat2LngAdjust,2) \t ASC \t限制3 – spiderplant0 2011-05-12 22:50:54

+0

我懷疑你可以用存儲過程做到這一點,但我恐怕沒有這方面的知識。我可能會用一些簡單的包裝邏輯(例如PHP)來處理這個問題,該邏輯運行第一個查詢,提取值並創建更新語句。理論上,您可以對多個郵政編碼運行「SELECT」查詢,對結果進行批量處理,然後創建一個大的多行REPLACE語句。 – 2011-05-12 22:52:17

1

你可以做一些類似這樣的東西:

UPDATE table1 
SET 
nearestPostcode1 = pc1, 
nearestPostcode2 = pc2, 
nearestPostcode3 = pc3 
FROM 
(SELECT pc1, pc2, pc3 FROM ....) t 
WHERE 
postcode = 'KY6 1DA'; 

我發現此相關的問題#2如何列轉換爲行:

MySQL - Rows to Columns

你的情況,你可以做點像

SELECT 
IF(@rownum=1,postcode,'')) AS pc1, 
IF(@rownum=2,postcode,'')) AS pc2, 
IF(@rownum=3,postcode,'')) AS pc2, 
FROM 
(SELECT postcode 
FROM postcodeTable 
ORDER BY <equation to calculate distance> ASC 
LIMIT 3) 

這裏是模擬在MySQL [1]的ROW_NUMBER()功能的黑客:

SELECT @rownum:[email protected]+1 rownum, t.* 
FROM (SELECT @rownum:=0) r, mytable t; 
+0

謝謝@peter然而,是pc1,pc2和pc3列?我的選擇查詢返回3行而不是3列。即它會返回最接近的3個郵編。我已經添加了一些更多的原始問題來解釋這一點。 – spiderplant0 2011-05-12 22:43:39

+0

我的意思是謝謝Ravi-Gummadi :) – spiderplant0 2011-05-12 22:57:40

+0

@ spiderplant0:修改了答案。我沒有有效地運行查詢,所以只是將它視爲僞代碼。 – rkg 2011-05-12 23:08:15

-1

每當我看到一個表,有他們的名字後1專櫃專欄中,我得到關注。

一般而言,存儲可以從已經存儲的數據中計算出來的數據是一個壞主意(TM)。如果您的應用突然需要最接近的郵政編碼,會發生什麼情況?如果郵政編碼邊界改變怎麼辦?

假設距離計算不是很複雜,從長遠來看,最好不要顯式存儲這些數據。

+0

@ chris-morgan計算3個最接近的郵政編碼需要很長時間才能運行。但是,這隻需要一次完成,後續的需要這些信息的數據庫查詢需要快速。關於是否壞主意的決定實際上總是取決於背景。 – spiderplant0 2011-05-12 22:56:17

+0

@ spiderplant0我明確地認識到,背景很重要,我總是喜歡在靈活性方面犯錯,因爲變化通常是有保證的。 – 2011-05-12 23:10:20