2011-07-07 84 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(我在工作中的同事),没有他们,我也不会远得到这一点。