Mapinfo重點及難點講解(一)
SQL查詢 重分區 無縫圖層 返回
一、SQL查詢
SQL Select的一般步驟:
1.打開你要查詢的表。你要查詢的表爲基礎表(Base Table)
2.選擇Query>SQL Select,填寫SQL Select對話框滿足你需要的那些分。按擊OK,Mapinfo進行查詢。
Mapinfo從你的基礎表中抽出數據,把查詢結果保存在一個被稱爲結果表的特殊臨時表中。結果表僅有滿足你的條件的行和列。結果表的默認名是Selection(儘管你可以在SQL Select對話框的Info Table Named位置上指定一個不同的結果表名)。
注意:以下第三條暗示:結果表既反映在Browser窗口,也反映在Map窗口中,換句話說,可收查詢結果保存爲另一個圖層。保存方法見下面的第5條。
3.如果你要看查詢結果,打開一個Map窗口或(和)一個Browser窗口。默認的是MapInfo自動以一個Browser窗口顯示結果表(除非你清除了SQL Select對話框中的Browser Results檢查盒)。
如果你的結果表被命名爲Selection(默認名),Browser窗就顯示一個不同的表名,例如Query1名Query2。這是因爲你瀏覽這個Selection表的瞬間,MapInfo對該表作了一個“快拍”,並命名這個快拍爲Queryn(n是數字,1或更大)。MapInfo主要按快拍是因爲“Selection”是一個特殊的表名,每當你選擇或不選擇某些行時,Selection都在動態變化。
在SQL Select對話框中,你可以爲你的結果表輸入一個另外的名字(例如,你可以命名你的結果表爲My-Query)。這就阻止了MapInfo把你的結果表重命名爲Queryn。
4.MapInfo自動選擇結果表中全部的行。這樣,在你執行了SQL Select之後,你就能夠接着執行選擇行的全套操作。例如,你可以(通過選擇Option>Region Style)對所有被選擇的行提供另一種充填色,或者你能夠Cut或Copy選擇的全部行。
通常,你對結果表所作的任何變化都會自動作用於你的原始(基礎)表。例如,如果你用SQL Select選擇了基礎表中的某些行,然後又從你的結果表中刪除了部分行,MapInfo就會從你的表中刪除相應的行。但是,如果你查詢產生了小計(Subtotals),你可以改變這個結果表而不影響基礎表。
5.如果你要作一個結果表的永久備份,選擇File>Save As。
如果你你不執行Save As存盤,該結果表將在你退出MapInfo時被刪除。
SQL Select對話框各區的填寫
Select Columns區
(1)利用這個區來指定在查詢表中將出現哪些列。例如查詢World表,可以指定Select Columns:Country,Population,Indust_Grwth,如果你要你的結果表有與你的原表相同的列組,那就在這個區輸入一個*號。
如果你要你的結果有一個與你的原表不同的列組,就要刪去這個*號並輸入由逗號分隔的列名(如下同)表達式列表。這個區能夠包括一個*號或者一個列表達式列表,但不能同時包括這兩種。要在你填Select Columns區之前填From Tables區。
如果你查詢涉及的不止一個有,各個列名之前必須有它的表名,二者之間用西文句號分隔。因此,如果你要執行一個涉及兩個表的查詢,其中之一是Canada表,並且你要查詢包括該表的Population列,那麼你必須用列表達式Canada.Population。當你使用兩個或多個表時,Columns下拉列表自動把表名插到各個列名之前。
(2)只選擇部分列出現在結果表中是有用的,特別是你的原表有很多列而你僅需操作其中的少數列時(或許因爲屏幕上只能同時顯示少數列)
(3)如何輸入一系列列名:
在From Tables區輸入一個表名,可用鍵盤打入,也可用鼠標從Table下拉列表中選入。
用鼠標在Select Columns區中按擊,使插入點出現在該區內。
用退格鍵或刪除鍵刪去*號(如果其中有*號),Select Columns區能夠包含一個*號或者一串列名,但不能同時包含這兩種。
從對話框右邊的Columns下拉列表中選擇一個列名。MapInfo把這個列名Copy到Select Columns區。
如果你的查詢還包括另外一些列名,從下拉列表中選擇另外的一些列名。每當你選擇另外的列名時,MapInfo自動插入逗號以分隔列名。
(4)計算某些列
SQL Select能夠計算出列(derived Columns)並把這些導出列存放到結果表中。導出列是MapInfo在中根據基礎表中已有的一個或多個列的內容計算出的一個特殊的臨時列。
例如,你的表或許含有字段Purchases92或Purchases93(分別代表各顧客在1992和1993年購物的總金額)。如果你要你的查詢結果顯示一個Total Purchases列,表示各顧客1992和1993年合起來的購物金額,你可以在你的Select Colomns區內包括一個導出列。在這個例子中,導出列應該有這樣的形式:
Purchases 92 + Purchases 93
同樣,你可能有一個包含有字段Fname(代表顧客的第一名)和Lname(顧客的後名)的顧客信息表。如果你要你的結果表包括顧客的全名,你也可以在你的Select Columns區包括一個導出列,在這個例子中,導出列會有這樣的形式:
Fname + “” + Lname
爲指定一個導出列,你就要在Select Columns區輸入一個表達式。一個導出列表達式是若干列名,操作符(例如+和-)和函數(例如Ucase$函數,它把一個字串轉換爲大寫的)的一個組合。
在指定導出列之前,你必須先在From Table區輸入一個或多個表名。
如何指定一個導出列表達式
按Select Columns區,在該區出現插入點。
刪除區內的*號
輸入一個列表達式。列表達式應該包括一個或多個列名,如果表達式包括一個以上的列名,這個表達式一般包含操作符(例如+或-)來把多個列組合成爲一個導出值。
有許多不同的函數和操作符能夠用於列表達式中。
如果需要爲列表達式指定一個別名。指定別名的方法是:在列表達式後打一個空格,然後再打入用雙引號括起來的別名。
別名是可選的。如果你給了你的列表達式一個別名,那麼,當你以Browser窗口顯示結果表時別名就會出現在這個列的頂上。如果你沒指定別名,MapInfo會用表達式的內容作爲別名(例如“Fname+Lname”)。
如果需要,指定另外的列名或導出列表達式。如果你輸入另外的列表達式,要輸入逗號以隔開不同的表達式。
下面的例子顯示一個執行加法的導出列表達式,把兩個數字列的值加起來。這個例子假定Purchases92和Purchases93均爲數字列:
Purchases92 + Purchases93
下一個例子顯示同樣的列表達式,附加上了一個可選的列別名(”Net_Purchases”):
Purchases92 + Purchases93 “Net_Purchases”
下一個例子顯示一個執行除法的導出列表達式,把Poppulagion列的內容除以一百萬:
Population/1000000 “Millions”
下一個例子顯示一個把兩個字串列組合起來的導出列表達式。這個例子假定Fname 和Lname都是字串列:
Fname+””+Lname “Full_name”
當列是字串列時,加操作符(+)執行字串聯接而不是數字相加。因此,表達式Fname + “ “ + Lname產生一個由第一名緊跟空格再後跟一名組成的字串。
下一個例子顯示一個導出列表達式怎樣結合函數調用。Proper$函數操作一個字串值並返回一個有正常大寫的字串(僅第一字母大寫):
Proper$(Fname+””+Lname) “Full_name”
下一個例子顯示如何用Format$函數重新格式化數字列。一般,數字列都沒有包含逗號,不幸的是,這使得讀大數有困難。下面的例子用Format$函數把逗號插入到Purchases93列中。這個例子假定Purchases93是一個數字列:
Format$(Purchases93,”$,#”) “Purchases_1993”,字串表達式“$,#”告訴Foramt$函數在列前顯示一個美元($)並在列內插入逗號。
下一個例子顯示一個導出列怎樣計算基礎表中各行的地理面積:
Area(Obj,”sqkm”) “Net_Area”
Obj是一特殊的列名,代表與表中各行相聯繫的地理對象。
Where Condition區
(1)通過行的排列順序聯接不同的表
如果兩個表沒有一個共同的列,你可以根據行的順序仍然能夠聯接這兩個表。如果你知道一個表的第一行與另一個表的第一行是相對應的,並且,一般地說,如果你知道第一個表的第n行與第二個表的第n行是對應的,那麼你就可以通過引用一個名叫RowID的特殊列來聯接這兩個表。
RowID列含有一個整數值,代表着表中各行的行號。因此,任何表的第一行都有一個爲1的RowID值,第2行有一個RowID值2,等等。
爲了聯接兩個表,讓MapInfo一個表的第n行與另一個表的第n行匹配起來,就要指定一個Where Condition表達式,形如下:
TABLE_1.RowID=TABLE_2.RowID
(2)從地理上(用地理操作符)聯接不同的表
當兩個表都有圖形對象時,MapInfo能夠根據這些對象之間的空間關係聯接這兩個表。所以,即使你的表沒有一個共同的列,你也有可能聯接不同的表。
地理操作符允許你選擇某些對象,根據它們與另外的某個對象的空間關係。MapInfo有一個與地理操作符一起使用的特殊列名,“Obj”或“Object”。這個列名指的是與你的表相邊系的圖形對象。
地理操作符要放到所指定的對象之間,地理操作符從操作符(Operators)下拉列表中選取。
下表列出了地理操作符:
Contaions(含有)
Object A Contains Object B
(如果B的形心在A的邊界內的某個位置上)
Contaions Entire(包含全部)
Object A Contains Entire Object B
(如果B的邊界全部在A的邊界內)
Within(在內)
Object A is Within Object B
(如果A的形心在B的邊界內側)
Entire Within(完全在內)
Objcte A is Entire Within Object B
(如果A的邊界全部在B的邊界內)
Intersects(相交)
Objcte A Intersects Object B
(如果它們至少有一個共同點或者它們中的一個完全在另一個內)
Contains與Within的比較是根據對象的形心,而Contains Entire與Entire Within的比較是根據整個對象。
如果A包括整個B,那麼A肯定包含B,如果A完全在B內,那麼A肯定在B內。
MapInfo執行簡單的含有和在內比較,比執行完全含有和完全在內要快。因此,除非你絕對相信某些對象是完全在另一些對象之內,否則你應該使用Contains和Within而不用Contains Entire或Entire Within。
地理操作符提供了一種聯接表的方法。當表中沒有你能建立起聯接的列時,你可以用地理操作符(在Where Condition區內)指定聯接關係。如果你要執行一個涉及一個Cities表和一個State表的兩表查詢,你可以用如下的表達式之一聯接兩個表:
Cities.Obj Within States.Obj
States.Obj Contains Cities.Obj
在任何一種情況下,MapInfo都能找到在各個州內的全部城市,然後把代表一個城市的一個行與含有它的州的行聯繫起來。用同樣的SQL查詢,你也能夠用集合功能來合計每個州的城市數,或者以州爲根據總結基於城市的數據。
當你有Counties 表和一個Customers表時,Counties是多邊形,Customers是點,你可以用下列地理表達式之一指一個集合聯接:
Customer.obj Within County.obj
County.obj Contains Customer.obj
地理操作符與Subselects結合特別有用(見Perferming Subselects)
(3)聯接兩個或更多的表(根據共同字段)
一般,你是把你的資料貯存在幾個不同的表中,你有你自已的數據文件,你也可能有從MapInfo購買的各種統計資料的數據庫。SQL允許你建立關聯以便你把這些不同表中的資料接到一起,成爲一個單獨的結果表。設想這樣一種情況:你有一個有人口統計交資料的Counties表(各個County按年齡段、種族和職業種類的人口數統計),你還可能有關於顧客訂單資料的數據庫。你想檢測一下這兩個表,看一定種類的訂單是否來自具有一定人口統計特徵的Counties。或許你想根據訂單與人口的統計特徵的組合選擇若干個Counties(縣)。要做到這一點,你必須能夠聯接這兩個表。
假設Counties表含有縣名,同樣訂單表的一個列也含有訂單來源的縣名,這樣,兩個表都有一個共同的字段,即縣名。MapInfo能夠用這個共同的字段來聯接這兩個表。
Countyname 1980人口,1990人口 Order# Customer County
Foster 1980人口,1990人口 478001 Franic Foster
Williamette 1980人口,1990人口 478002 James Foster
Mason 1980人口,1990人口 478003 Wick mason
Counties表 Order表
在SQL Select 對話框中,你用Where Condition區告訴MapInfo如何聯接這兩個表。在這個區內填寫如下:
Select Columns: *
Frome Table: Counties,Order
Where Condition: Counties.Countyname=Order.county
表名(在From Tables區)的順序是重要的。如果兩個表都含有Map對象,結果表將只含有排列在From Tables區中第一個表的Map對象。另外,當查詢完成時,MapInfo會自動選擇列在From Tables區第一個表的部分或全部行。這樣,在前例中,MapInfo會選擇Counties表的部分或全部行。其結果也會包括從Orders表中拷貝來的數據,但Orders表本身不會被選擇。
在Where Condition區中,列的順序必須與From Tables區中表的順序相匹配。在上例中,From Tables區把Counties表放到了Qoders表之前,因此,Where Condition區必須把Counties.CountiName列放在Orders.County列之前。如果顛倒這兩個表在From Tables區內的順序,你也必須顛倒在Where Contition區內列名的順序。
當你聯接兩個表時,結果表的行數取決兩個匹配的好壞。假定你有一個10000行的Order表,要把這個Order表與有50行的States表聯接。結果表可能有10000行之多。但是如果Orders表中的某些行沒有與States表中的行相匹配。結果表就會少於10000行。因此,如果Orders表中有400行無state名(或許由於數據輸入錯誤),並且如果這個關聯是依賴State名,結果表就可能只有9600個行了。
當SQL Select對話框聯接兩個表時,你指定的如何聯接這兩個表的子句(Clause(s))必須放在Where Condition區內的其它子名之前。
你可以用Update Column來修改SQL Select多表聯接的結果表。當你要更新一個表中帶有另一個表的信息的一個列時,你可以:
用SQL Select聯接這兩個表。
針對Selection表使用Update Column。
更新會自動影響到相應的基礎表。
(4)次選擇(Subselects)
MapInfo允許SQL Select中的再次選擇。再選擇是放在SQL Select對話框Where Condition區內裏面的一個選擇語句。MapInfo首先處理Subselects,然後用這個Subselects的結果去處理主要的SQL Select。
例如,假定你要選出1990年人口大於全國各州平均值的全部州。換句話說,如果平均州人口是5百萬,你要選出所有平均人口大於5百萬的州。在實行中,你要在Where Condition區中使用如下的過濾標準:
Pop_1990>平均人口
然而,你並不知道那平均值是多少。但是,你知道MapInfo能夠用如下集合表達式計算出那個平均值:
Avg(Pop_199)
爲了計算平均州人口,要在Where Condition區輸入一個再選擇(Subselect)。Where Condition區那時能夠比較對Pop_1990列再選擇的結果。要進行那樣一種查詢,如下填寫SQL Select對話框。
Select Columns: *
From Table: States
Where Condition: Pop_1990>(Sekect Avg(Pop_1990) From States)
再選擇是在Where Condition區內,在>操作符之後。再選擇必須用園括號括起來。
最有用的再選擇包括一個Select子句,一個from子句和一個Where子句,象下面這樣:
Select某些列from某些表where某些條件存在。
考慮如下的SQL Select,它選擇各州中人口大於4000000的全部城市:
Select Columns: *
From table: cities
Where Condition: obj within any(Select obj from states where Pop_1990>4000000)
再選擇返回代表1990年人口大於400000的全部州的地理對象。然後主選擇語句設到被再選擇選中了的州內全部城市。注意:主選擇語句用了一個地理操作符(Within)來做這個事情。
雖然前一查詢用兩個表,States表和Cities表,但Cities是出現From Tables區的僅有的表。這是因爲在再選擇中使用了States。如果一個表僅僅是被用於再選擇內,那麼這個表的表名不需要出現在From Tables區中。
在下一個例子中,我們選擇與田西納州相交的所有州,換言之,所有相鄰的州。
Select columns: *
From tables: states
Where conditions: obj Intersects(select obj from states where
state=”TN”
首先,MapInfo執行再選擇:
Selectobj from states where state=”TN”
再選擇找到了代表田納西州的圖形對象。然後主Where condition找到了States表中與代表田納西州的圖形相交的全部對象。你可以用類似的查詢選擇與某給定街道相交的全部街道。
現考慮這個例子:
Select columns: *
From Tables: County
Where Condition: County.obj contains any(select obj from dealers)
這個查詢找到含有銷售商的所有縣。主Where condition有這樣的一個形式:
一個縣對象Contains一個經銷商對象。
經銷商對象組是由再選擇:Select obj from dealers產生的。MapInfo選擇代表含有經銷商的各個縣對象的行。