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:我说的停车是指高速公路上的加油站。在这种情况下,边缘将是高速公路,节点可能是城市。