2011-07-07 49 views
7

Tôi đã cố gắng thu hẹp vấn đề càng nhiều càng tốt, nó vẫn còn là một cái gì đó. Đây là câu hỏi mà không làm việc theo cách tôi muốn nó:GROUP BY với tổng hợp và 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 

Dưới đây là những gì tôi nhận được:

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

và đây là những gì tôi muốn:

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

Nhưng hãy để tôi giải thích một chút ...

Tôi có biểu đồ, giả sử như vậy:

node1 
     | 
    node2 
/ \ 
node3 node4 
    |  | 
node5 node6 

Vì vậy, tôi có một bảng tôi gọi tbl_edges như thế này:

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

Bây giờ mỗi edge có "stop_over s" ở một khoảng cách nhất định (để nodeA). Do đó, tôi có bảng tbl_stopover như sau:

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

Tại sao truy vấn này?
Giả sử tôi muốn tính khoảng cách giữa các số stop_over s. Trong phạm vi một cạnh không có vấn đề gì. Trên các cạnh sẽ khó khăn hơn. Nhưng nếu tôi có hai cạnh được kết nối và không có kết nối khác tôi cũng có thể tính toán khoảng cách. Dưới đây là một ví dụ giả định tất cả các cạnh có một length của 10:

cạnh 23 có stop_over (id = 3) tại quận = 9, cạnh 35 có stop_over (id = 6) tại quận = 5. Do đó khoảng cách giữa hai số này là stop_over s là:

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

Tôi không chắc liệu mình có tự làm rõ hay không. Nếu điều này là không dễ hiểu, hãy đặt câu hỏi và tôi sẽ cố hết sức để làm cho điều này dễ hiểu hơn.

+0

"stop_over" là gì? –

+0

@ypercube: by stop_over Tôi có ý nghĩa giống như một trạm xăng trên đường cao tốc. Trong bối cảnh đó các cạnh sẽ là đường cao tốc, và các nút có thể là ... thành phố. – AudioDroid

Trả lời

4

MySQL cho phép bạn làm điều gì đó ngớ ngẩn - hiển thị các trường trong truy vấn tổng hợp không phải là một phần của GROUP BY hoặc hàm tổng hợp như MAX. Khi bạn làm điều này, bạn sẽ nhận được kết quả ngẫu nhiên (như bạn đã nói) cho các trường còn lại.

Trong truy vấn của bạn, bạn đang làm điều này hai lần - một lần trong truy vấn bên trong của bạn (id2 không phải là một phần của một tổng GROUP BY hoặc) và một lần vào bên ngoài.

Chuẩn bị cho kết quả ngẫu nhiên!

Để khắc phục nó, hãy thử một cái gì đó như thế này:

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 

Những thay đổi chủ yếu là danh sách trường rõ ràng (lưu ý rằng tôi loại bỏ các id_edge kể từ khi bạn đang tham gia vào id1 và đã có lĩnh vực đó), và thêm các trường bổ sung cho cả hai mệnh đề bên trong và bên ngoài GROUP BY.

Nếu điều này cung cấp cho bạn nhiều hàng hơn bạn muốn thì bạn có thể cần giải thích thêm về tập hợp kết quả mong muốn của mình. Một cái gì đó như thế này là cách duy nhất để đảm bảo bạn có được các nhóm thích hợp.

+0

Đó vẫn không phải những gì tôi muốn. Nhưng đó là sự giúp đỡ to lớn, đặc biệt là điểm về "những điều ngớ ngẩn" ;-). Tôi nghĩ điều đó sẽ đưa tôi đến đó. Hãy xem ... – AudioDroid

+0

Hm, tôi chỉ muốn hai cạnh của một nút chỉ có hai cạnh, và sau đó là stop_over xa nhất từ ​​edge1.I tiếp tục cố gắng ... – AudioDroid

+0

@Audio - bạn có thể đăng thêm một số thông tin vào bản gốc câu hỏi? – JNK

1

OK. Đây là có vẻ như là câu trả lời cho câu hỏi của tôi. Tôi sẽ làm một số "điều tra" hơn nữa mặc dù, bởi vì tôi không chắc chắn nếu điều này là đáng tin cậy. Nếu ai đó có một số mặc dù về điều này, xin vui lòng để lại một bình luận.

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 

Xin cảm ơn JNK (đồng nghiệp của tôi tại nơi làm việc) mà không có người mà tôi sẽ không đạt được điều này.

Các vấn đề liên quan