2014-06-05 43 views
0

我試圖找到解決方案,並且當記錄數低於某個數時它很容易解決。但...MSSQL 2008R2避免矩陣中的重複項目,如表

我有一個81,590條記錄的原始列表。

Id Loc Sales LatLong 
1 a 100 ... 
2 b 110 ... 
3 c 105 ... 
4 d 125 ... 
5 e 123 ... 
6 f 35 ... 
. 
. 
. 
81,590 ... ... ... 

我需要比較列表中的所有項目。

Id L1 L2 Dist  
    1 a a 0 --> Not needed. Self comparison. 
    2 a b 26 
    3 a c 150 --> Not needed. Distance >100. 
    4 a d 58 
    5 b a 26 --> Not needed. Repeated record. 
    6 b b 0 --> Not needed. Self comparison. 
    7 b c 15 
    8 b d 151 --> Not needed. Distance >100. 
    9 c a 150 --> Not needed. Repeated record. 
    10 c b 15 --> Not needed. Repeated record. 
    11 c c 0 --> Not needed. Self comparison. 
    12 c d 75 
    13 d a 58 --> Not needed. Repeated record. 
    14 d b 151 --> Not needed. Repeated record. 
    15 d c 75 --> Not needed. Repeated record. 
    16 d d 0 --> Not needed. Self comparison. 

但是如圖旁邊以上的記錄,最終結果需要是列表:

1)比較記錄相對於彼此僅當它們位於一定距離,說< 100英里。

2)不包含重複的意義,即將Loc1與Loc2進行比較與將Loc2與Loc1進行比較相同。

3)很明顯,沒有必要比較Loc1本身。

最終的結果將是:

Id L1 L2 Dist 
    2 a b 26 
    4 a d 58 
    7 b c 15 
    12 c d 75 

方法:

理論上,對自己比較所有項目後的總記錄數爲81590^2 = 6656928100個記錄。

減去重複的迭代(LocA-LocB = LocB-LocA)將意味着6,656,928,100/2 = 3,328,464,050。

通過擺脫自我重複迭代(LocA-LocA)進一步清理應該是3,328,464,050 - 81,590 = 3,328,382,460。

然後,我可以擺脫距離大於100英里的所有記錄。

這是非常低效的,我會建立一個表,60億分美元的記錄,然後刪除一半,等等,等等等等


有沒有在一個多到達最終產品的方法更高效(少步驟,少選擇/刪除/更新)的方式?

將最終數據集插入目標所需的select語句是什麼?

這聽起來像是有一個表與自己的連接,並通過密鑰的迭代過濾,但這裏是我卡住的地方。

+0

Wat?你有數據,需要根據距離比較東西,但你怎麼知道它什麼時候可以匹配?它完全基於距離嗎?我害怕匿名化你的問題,你已經掩蓋了有用的位 – billinkc

+0

是的,這完全是距離。我正在使用經濟普查數據來比較地區銷售水平與<100以外的其他地區的銷售水平。 – lwall

+0

密蘇里州堪薩斯城花費30美元。哥倫比亞花費10美元。StL花費1000美元,彼此之間的距離都超過100英里。預期的產出會顯示什麼? Kansas City-> Columbia 30:10,KC-> StL 30:1000或KC-> Columbia,KC-> StL,Columbia-> StL。換句話說,你是試圖爲整個領域生成結果還是從中心點找到所有的位置? – billinkc

回答

0

你用什麼算法計算兩點之間的距離?簡單的「世界是平坦的」笛卡爾數學,還是那個三角學滿載的「這個詞是扁圓形的」呢?這可能會變成嚴重的CPU需求。

可能最好生成一個「位於該位置的距離X範圍內的位置」的表並且永久存儲它;除了地震等重大事件之外,它不會改變。

查詢明智的,底座連接很簡單:

SELECT 
    t1.Loc L1 
    ,t2.Loc L2 
from MyTable t1 
    inner join MyTable t2 
    on t2.Loc > t1.Loc 

如果有,比如說距離公式,一個名爲「distanceFunction」的功能,它可能看起來像:

WITH cteCalc as (
    select 
     t1.Loc L1 
     ,t2.Loc L2 
     ,dbo.distanceFunction(t1.LatLong, t2.LatLong) Dist 
    from MyTable t1 
     inner join MyTable t2 
     on t2.Loc > t1.Loc 
    where dbo.distanceFunction(t1.LatLong, t2.LatLong) < @MaxDistance) 
INSERT TargetTable (L1, L2, Dist) 
SELECT 
    L1 
    ,L2 
    ,Dist 
    where Dist <= @MaxDistance 

當然,這可能會破壞你的系統,如果僅僅是因爲當你向目標表寫入幾十億行時事務日誌會變得太大。我想說建立一個循環,處理依次在每個位置,最終的查詢關鍵詞,比如:

WITH cteCalc as (
    select 
     t1.Loc L1 
     ,t2.Loc L2 
     ,dbo.distanceFunction(t1.LatLong, t2.LatLong) Dist 
    from MyTable t1 
     inner join MyTable t2 
     on t2.Loc > t1.Loc 
    where dbo.distanceFunction(t1.LatLong, t2.LatLong) < @MaxDistance 
     and t1.Loc = @ThisIterationLoc) 
INSERT TargetTable (L1, L2, Dist) 
SELECT 
    L1 
    ,L2 
    ,Dist 
    where Dist <= @MaxDistance 

第一遍返回81589少取太遙遠了,第二回合爲81588來處理,等等。

+0

如果沒有其他數據或聰明的技巧,您將不得不將每一行與其他行匹配並計算距離。育。 –

0

這裏是我將如何解決這一問題的提綱:

  1. 緯度和經度看跌指標
  2. 做數學爲緯度和長的距離,爲的範圍內(盒)您距離。然後你知道你的距離(因爲方塊不是一個圓圈)包含在這個三角洲中。你也知道它不在這個三角洲之外。這大大限制了這個問題。

    例如,如果緯度和長度的變化對於您的距離爲10,那麼您的方框的位置(100,100)將由緯度和長度的(95,95)和(105,105)值定義。

  3. 編寫一個查看每個元素(來自最低ID)的查詢,並搜索緯度和日誌增量內的其他元素(使用更大的ID以避免重複)並將其保存到臨時表中。
  4. 迭代該表並做一個完整的計算,看看它是否在你的距離的圓(不是框)內。