Mysql 具有聚合和内部联接的分组依据
我试图尽可能缩小这个问题的范围,但它仍然很重要。这是一个无法按我所希望的方式工作的查询:Mysql 具有聚合和内部联接的分组依据,mysql,sql,Mysql,Sql,我试图尽可能缩小这个问题的范围,但它仍然很重要。这是一个无法按我所希望的方式工作的查询: 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 = edge
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_边,如下所示:
| id | nodeA | node B |
------------------------
| 12 | 1 | 2 |
| 23 | 2 | 3 |
| 24 | 2 | 4 |
| 35 | 3 | 5 |
| 46 | 4 | 6 |
------------------------
| id | edge | dist |
------------------------
| 1 | 12 | 5 |
| 2 | 23 | 2 |
| 3 | 23 | 9 |
| 4 | 24 | 5 |
| 5 | 24 | 9 |
| 6 | 35 | 5 |
| 7 | 46 | 5 |
------------------------
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
现在,每个边
在一定距离(到nodeA
)有“stop_over
s”。因此,我有一个表tbl_中途停留,如下所示:
| id | nodeA | node B |
------------------------
| 12 | 1 | 2 |
| 23 | 2 | 3 |
| 24 | 2 | 4 |
| 35 | 3 | 5 |
| 46 | 4 | 6 |
------------------------
| id | edge | dist |
------------------------
| 1 | 12 | 5 |
| 2 | 23 | 2 |
| 3 | 23 | 9 |
| 4 | 24 | 5 |
| 5 | 24 | 9 |
| 6 | 35 | 5 |
| 7 | 46 | 5 |
------------------------
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
为什么要进行此查询?假设我想计算
stop\u over
s之间的距离在一条没有问题的边内穿过边缘,这会变得更加困难。但是如果有两条边是连接的,没有其他连接,我也可以计算距离。这里是一个假设所有边的长度为10的示例:
边缘23
在距离=9处有一个停止(id=3
),边缘35
在距离=5处有一个停止(id=6
)。因此,这两个stop\u over
s之间的距离为:
dist = (length - dist_id3) + dist_id5 = (10-9) + 5
我不确定我是否把自己说清楚了。如果这是不可理解的,请随意提问,我会尽我所能让这更容易理解。MySQL允许您做一些愚蠢的事情-在聚合查询中显示不属于分组依据的字段或类似MAX
的聚合函数。当您这样做时,您会得到剩余字段的随机(如您所说)结果
在您的查询中,您将执行两次,一次在内部查询中(id2
不是分组依据或聚合的一部分),一次在外部查询中
准备随机结果强>
要解决此问题,请尝试以下方法:
| id | nodeA | node B |
------------------------
| 12 | 1 | 2 |
| 23 | 2 | 3 |
| 24 | 2 | 4 |
| 35 | 3 | 5 |
| 46 | 4 | 6 |
------------------------
| id | edge | dist |
------------------------
| 1 | 12 | 5 |
| 2 | 23 | 2 |
| 3 | 23 | 9 |
| 4 | 24 | 5 |
| 5 | 24 | 9 |
| 6 | 35 | 5 |
| 7 | 46 | 5 |
------------------------
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\u边
,因为您正在加入id1
,并且已经有了该字段),以及在内部和外部GROUP BY
子句中添加了额外的字段
如果这给了您比您想要的更多的行,那么您可能需要更多地解释您想要的结果集。这样做是确保获得适当分组的唯一方法。好的。这似乎是我问题的答案。不过,我会做一些进一步的“调查”,因为我不确定这是否可靠。如果有人对此有什么想法,请留下评论
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
(我工作中的同事),没有他我不会走这么远。这仍然不是我想要的。但它有很大的帮助,特别是关于“愚蠢的事情”的观点。我想这会让我达到目的。让我看看……嗯,我只想要一个只有两条边的节点的两条边,然后是距离边1最远的停止点。我一直在尝试…@Audio-你能在原始问题中发布更多信息吗?好的,我会的。但是,让我告诉您,组中最内部连接的“extra”'edges2.id'的方向是相反的。但是我知道可能必须在那里。@Audio-您可以不用它就尝试,因为您正在加入,并且无论如何不应该在那里得到多个返回行,所以它可能没问题。一般来说,这只是一种不好的模式。@ypercube:我说的停车是指高速公路上的加油站。在这种情况下,边缘将是高速公路,节点可能是城市。