您需要使用额外的子查询来找出每个机械师的最小半径是多少(半径大于距离),然后您可以将其连接回您的两个表并从两个表中获取您需要的所有列信息表:
SELECT m.ID, mz.Zone, m.distance, mz.radius
FROM Mechanics m
INNER JOIN mechanic_zones mz
ON mz.Mechanic_ID = m.ID
INNER JOIN
( SELECT m.ID,
MIN(mz.radius) AS radius
FROM Mechanics m
INNER JOIN mechanic_zones mz
ON mz.Mechanic_ID = m.ID
WHERE mz.radius > M.distance
GROUP BY m.ID
) MinZone
ON MinZone.ID = m.ID
AND MinZone.radius= mz.radius
ORDER BY mz.Zone;
SQL Fiddle 示例
如果您实际上不想知道所选区域的半径,并且半径最小的区域将始终具有您可以使用的最低字母:
SELECT m.ID, mz.MinZone, m.distance
FROM Mechanics m
INNER JOIN
( SELECT m.ID,
MIN(mz.Zone) AS Zone
FROM Mechanics m
INNER JOIN mechanic_zones mz
ON mz.Mechanic_ID = m.ID
WHERE mz.radius > M.distance
GROUP BY m.ID
) MinZone
ON MinZone.ID = m.ID
ORDER BY MinZone.Zone;
SQL Fiddle 示例
编辑
您的小提琴与我将使用的非常接近,但我会使用以下内容,以便计算只进行一次:
SELECT m.id, m.name, m.distance, m.radius, m.zone
FROM ( SELECT m.ID,
m.Name,
m.Distance,
MIN(mz.radius) AS radius
FROM ( SELECT ID, Name, (1 * Distance) AS Distance
FROM Mechanics
) m
INNER JOIN mechanic_zones mz
ON mz.Mechanic_ID = m.ID
WHERE mz.radius > M.distance
GROUP BY m.ID, m.Name, m.Distance
) m
INNER JOIN mechanic_zones mz
ON mz.Mechanic_ID = m.ID
AND mz.radius = m.radius;
SQL Fiddle 示例
这背后的原因是您的查询在选择列表中有列,而不是在分组依据中,因此不能保证返回的半径是最低的。例如,如果您更改将记录插入到 mechanic_zones 的顺序(如本小提琴中所示),您的结果将变为:
ID NAME DTJ RADIUS ZONE
1 Jon 2 10 a
2 Paul 11 50 b
3 George 5 5 a
代替
ID NAME DTJ RADIUS ZONE
1 Jon 2 5 a
2 Paul 11 20 b
3 George 5 5 a
如您所见,Jon 的半径是错误的。为了在下面进一步解释这一点,我摘录了我写的关于 MySQL 实现隐式分组的缺点的解释。
我建议尽可能避免 MySQL 提供的隐式分组,我的意思是在选择列表中包含列,即使它们不包含在聚合函数或 group by 子句中。
想象一下下面的简单表(T):
ID | Column1 | Column2 |
----|---------+----------|
1 | A | X |
2 | A | Y |
在 MySQL 中,您可以编写
SELECT ID, Column1, Column2
FROM T
GROUP BY Column1;
这实际上打破了 SQL 标准,但它在 MySQL 中有效,但问题是它是不确定的,结果:
ID | Column1 | Column2 |
----|---------+----------|
1 | A | X |
不比正确或不正确
ID | Column1 | Column2 |
----|---------+----------|
2 | A | Y |
所以你说的是给我一个不同的值Column1
,两个结果集都满足,那么你怎么知道你会得到哪一个?好吧,您不知道,这似乎是一个相当流行的误解,您可以添加和ORDER BY
子句来影响结果,例如以下查询:
SELECT ID, Column1, Column2
FROM T
GROUP BY Column1
ORDER BY ID DESC;
将确保您获得以下结果:
ID | Column1 | Column2 |
----|---------+----------|
2 | A | Y |
由于ORDER BY ID DESC
, 然而这不是真的(如此处所示)。
MMySQL文档状态:
服务器可以从每个组中自由选择任何值,因此除非它们相同,否则选择的值是不确定的。此外,从每个组中选择值不会受到添加 ORDER BY 子句的影响。
因此,即使您有这样的订单,直到每组选择一行之后才适用,并且这一行是不确定的。
SQL 标准确实允许选择列表中的列不包含在 GROUP BY 或聚合函数中,但是这些列必须在功能上依赖于 GROUP BY 中的列。例如,示例表中的 ID 是 PRIMARY KEY,所以我们知道它在表中是唯一的,所以下面的查询符合 SQL 标准,在 MySQL 中运行,目前在许多 DBMS 中会失败(在编写 Postgresql 时)是我所知道的最接近正确实施标准的 DBMS):
SELECT ID, Column1, Column2
FROM T
GROUP BY ID;
由于每一行的 ID 是唯一的,因此每个 ID 只能有一个值Column1
,一个值Column2
对于每一行返回的内容没有歧义。