2011-07-07 115 views
7

我試圖儘可能縮小問題的範圍,但它還是很有意思的。這是一個不工作的方式我想查詢它:帶聚合的GROUP BY和INNER JOIN

SELECT *, MAX(tbl_stopover.dist) 
FROM tbl_stopover 
INNER JOIN 
    (SELECT edges1.id id1, edges2.id id2, COUNT(edges1.id) numConn 
    FROM tbl_edges edges1 
    INNER JOIN tbl_edges edges2 
    ON edges1.nodeB = edges2.nodeA 
    GROUP BY edges1.id HAVING numConn = 1) AS tbl_conn 
ON tbl_stopover.id_edge = tbl_conn.id1 
GROUP BY id_edge 

這裏是我所得到的:

|id | edge | dist | id1 | id2 | numConn | MAX(tbl_stopover.dist) | 
------------------------------------------------------------------ 
|2 | 23 | 2 | 23 | 35 | 1  | 9      | 
|4 | 24 | 5 | 24 | 46 | 1  | 9      | 
------------------------------------------------------------------ 

,這是我想要的東西:

|id | edge | dist | id1 | id2 | numConn | MAX(tbl_stopover.dist) | 
------------------------------------------------------------------ 
|3 | 23 | 9 | 23 | 35 | 1  | 9      | 
|5 | 24 | 9 | 24 | 46 | 1  | 9      | 
------------------------------------------------------------------ 

但讓我詳細說一下...

我有一個圖,讓我們這樣說吧:

node1 
     | 
    node2 
/ \ 
node3 node4 
    |  | 
node5 node6 

因此我有一個表我稱tbl_edges這樣的:

| id | nodeA | node B | 
------------------------ 
| 12 | 1 | 2 | 
| 23 | 2 | 3 | 
| 24 | 2 | 4 | 
| 35 | 3 | 5 | 
| 46 | 4 | 6 | 
------------------------ 

現在每個edge具有 「stop_over的」 在一定的距離(到nodeA)。因此,我有一個像這樣的表tbl_stopover:

| id | edge | dist | 
------------------------ 
| 1 | 12 | 5 | 
| 2 | 23 | 2 | 
| 3 | 23 | 9 | 
| 4 | 24 | 5 | 
| 5 | 24 | 9 | 
| 6 | 35 | 5 | 
| 7 | 46 | 5 | 
------------------------ 

爲什麼這個查詢?
我們假設我想計算stop_over之間的距離。 之內的一個優點是沒有問題的。 跨越邊緣變得更加困難。但是,如果我有兩條連接的邊,並且沒有其他連接,我也可以計算距離。此處作爲一例假設所有邊緣具有length 10:

邊緣23具有DIST = 9 stop_over(ID = 3),邊緣35具有DIST = 5 stop_over(ID = 6)。因此,這兩個stop_over之間的距離是:

dist = (length - dist_id3) + dist_id5 = (10-9) + 5 

我不知道我是否讓自己清楚。如果這是不可理解的,請隨時提問,我會盡我所能讓這一點更容易理解。

+0

什麼是「stop_over」? –

+0

@ypercube:by stop_over我的意思是像高速公路上的一個加油站。在這種情況下,邊緣將是高速公路,節點可能是......城市。 – AudioDroid

回答

4

MySQL允許你做一些傻事 - 在不屬於GROUP BY的集合查詢中顯示字段,或者在MAX之類的集合函數中顯示字段。當你這樣做時,你會得到隨機的(如你所說)結果爲剩餘的領域。

在查詢你正在做這個兩次 - 一旦在你的內心查詢(id2不是GROUP BY或集合的一部分)和外一次。

準備隨機結果!

爲了解決這個問題,嘗試這樣的事情:

SELECT tbl_stopover.id, 
     tbl_stopover.dist, 
     tbl_conn.id1, 
     tbl_conn.id2, 
     tbl_conn.numConn, 
     MAX(tbl_stopover.dist) 
FROM tbl_stopover 
INNER JOIN 
    (SELECT edges1.id id1, edges2.id id2, COUNT(edges1.id) numConn 
    FROM tbl_edges edges1 
    INNER JOIN tbl_edges edges2 
    ON edges1.nodeB = edges2.nodeA 
    GROUP BY edges1.id, edges2.id 
    HAVING numConn = 1) AS tbl_conn 
ON tbl_stopover.id_edge = tbl_conn.id1 
GROUP BY tbl_stopover.id, 
     tbl_stopover.dist, 
     tbl_conn.id1, 
     tbl_conn.id2, 
     tbl_conn.numConn 

的主要變化是明確的字段列表(請注意,我刪除了id_edge,因爲你是在id1加入和已經擁有的那場),和在內部和外部GROUP BY子句中增加額外的字段。

如果這給你比你想要的更多的行,那麼你可能需要解釋更多關於你想要的結果集。像這樣的東西是確保您獲得適當分組的唯一方法。

+0

這仍然不是我想要的。但它有很大的幫助,特別是關於「愚蠢的事情」的觀點;-)。我認爲那會讓我在那裏。讓我們來看看...... – AudioDroid

+0

嗯,我只想要一個節點的兩條邊只有兩條邊,然後離edge1最遠的stop_over。我一直試圖... – AudioDroid

+0

@Audio - 你可以發佈一些更多的信息到原始題? – JNK

1

好的。這似乎是我的問題的答案。我會做一些進一步的調查,因爲我不確定這是否可靠。如果有人對此有所瞭解,請發表評論。

SELECT tbl.id, tbl.dist, tbl.id1, tbl.id2, MAX(dist) maxDist 
FROM 
(
    SELECT tbl_stopover.id, 
     tbl_stopover.dist, 
     tbl_conn.id1, 
     tbl_conn.id2, 
     tbl_conn.numConn 
    FROM tbl_stopover 
    INNER JOIN 
    (SELECT edges1.id id1, edges2.id id2, COUNT(edges1.id) numConn 
    FROM tbl_edges edges1 
    INNER JOIN tbl_edges edges2 
    ON edges1.nodeB = edges2.nodeA 
    GROUP BY edges1.id 
    HAVING numConn = 1) AS tbl_conn 
    ON tbl_stopover.id_edge = tbl_conn.id1 
    GROUP BY tbl_stopover.dist, tbl_conn.id1 
    ORDER BY dist DESC) AS tbl 
GROUP BY tbl.id1, tbl.id2 

感謝JNK(我在工作中的同事),沒有他們,我也不會遠得到這一點。