MySQL有条件的连接使用



在查询中,是否可以有条件地选择要使用的连接?在下面的查询中,m.bodyNo有时为空,连接使用m.chassisNo来显示数据,我希望它显示具有值的结果。

SELECT m.`seriesYear`, m.`bodyNo`, m.`modelDesc` 
FROM parts_parsed p
LEFT JOIN parts_modelno m ON p.`modelNo` = m.`bodyNo` 
WHERE p.`partNo` = '$PartNos'

尝试两个连接带来了我的查询测试器(HeidiSQL)中的所有数据,它为两个连接的相对列提供了相同的名称,但需要为每个值提供别名,并在PHP中做很多条件,所以我正在寻找更直接的东西。也许像COALESCE这样的东西可以做到这一点,但不确定如何应用它。谁能告诉我该怎么做?

SELECT m1.`seriesYear`, m1.`bodyNo`, m1.`modelDesc`, m2.`seriesYear`, m2.`bodyNo`, m2.`modelDesc`  
FROM parts_parsed p
LEFT JOIN parts_modelno m1 ON p.`modelNo` = m1.`chassisNo` 
LEFT JOIN parts_modelno m2 ON p.`bodyNo` = m2.`bodyNo` 
WHERE p.`partNo` = '$PartNos'

如果它没有丢失格式,它就是parse_parts的一个示例:

ID  pageNo  baseGroup   partID  partNo  modelNo bodyNo  isRHD
1       1       0         1     391906  2201              0
2       1       0         1     391906  2202              0
3       1       0         1     391906  2211              0
4       1       0         1     391906  2220              0
5       1       0         1     391906  2222              0
43493   315     30      9983    386405            2250    0
43494   315     30      9983    386405            2251    0
43495   315     30      9983    386405            2270    0
43496   315     30      9983    386405            2271    0
43497   315     30      9984    438463            2650    0

这是parts_modelno

的一个示例
ID  seriesYear  bodyNo  chassisNo   engineNo    modelDesc
1   1948-49     2213        2213    G600000    HEARSE AND AMBULANCE
2   1948-49     2250        2226    G600000    7 PASS, CUSTOM EIGHT LIMOUSINE
3   1948-49     2251        2226    G600000    7 PASS, CUSTOM EIGHT SEDAN
4   1948-49     2252        2206    G600000    6 PASS, CUSTOM EIGHT SEDAN
5   1948-49     2255        2206    G600000    6 PASS, CUSTOM EIGHT CLUB SEDAN
6   1948-49     2259        2233    G600000    6 PASS, CUSTOM EIGHT CONVERTIBLE VICTORIA
7   1948-49     2262        2211    G200000    6 PASS, DELUXE EIGHT TOURING SEDAN
8   1948-49     2265        2211    G200000    6 PASS, DELUXE EIGHT CLUB SEDAN
9   1948-49     2270        2222    G400000    7 PASS, DELUXE SUPER EIGHT LIMOUSINE
10  1948-49     2271        2222    G400000    7 PASS, DELUXE SUPER EIGHT SEDAN

parts_modelno在bodyNo和chassisNo列的所有行中都有完全填充的值,而parts_parts有bodyNo或modelNo,只有少数例外,两者都有,但在这些少数情况下,这两个值是相同的。parts_modelno。chassisNo匹配parts_parsed.modelNo

您可以使用这样的case方法…

SELECT m1.`seriesYear`,
m1.`bodyNo`,
m1.`modelDesc`,
m2.`seriesYear`,
m2.`bodyNo`,
m2.`modelDesc`
CASE
WHEN m2.value <> "" THEN m2.value
ELSE m1.value
END AS someName
FROM parts_parsed p
LEFT JOIN parts_modelno m1 ON p.`modelNo` = m1.`chassisNo`
LEFT JOIN parts_modelno m2 ON p.`modelNo` = m2.`bodyNo`
WHERE p.`partNo` = '$PartNos'

在各种评论中,您声明您并不真正关心性能,在这种情况下,您只想要最简单和最易于维护的代码?

所以,只是在连接谓词中使用OR吗?

SELECT
p.`baseGroup`,
m.`seriesYear`,
m.`modelDesc`,
m.`bodyNo`,
m.`chassisNo` AS modelNo 
FROM
parts_parsed   p
LEFT JOIN
parts_modelno  m
ON p.`bodyNo`  = m.`bodyNo` 
OR p.`modelNo` = m.`chassisNo` 
WHERE
p.`partNo` = '$PartNos'

假设p永远不会同时具有bodyNomodelNo填充。如果可能的话,你需要用一个你想要的行为的例子来更新这个问题。

如前所述,这段代码还意味着索引可以而不是用于优化查询计划。

编辑:

如果性能很重要(它应该,即使你只意味着cpu和磁盘利用率而不是用户体验),你应该简单地UNION两个查询。这允许优化器充分利用索引来避免无意义的读取,选择更好的连接实现,等等。

SELECT
*
FROM
(
SELECT
p.`baseGroup`,
p.`partNo`,
m.`seriesYear`,
m.`modelDesc`,
m.`bodyNo`,
m.`chassisNo` AS modelNo 
FROM
parts_parsed   p
INNER JOIN
parts_modelno  m
ON p.`bodyNo`  = m.`bodyNo` 
UNION ALL
SELECT
p.`baseGroup`,
p.`partNo`,
m.`seriesYear`,
m.`modelDesc`,
m.`bodyNo`,
m.`chassisNo` AS modelNo 
FROM
parts_parsed   p
INNER JOIN
parts_modelno  m
ON p.`modelNo` = m.`chassisNo` 
)
part_list
WHERE
`partNo` = '$PartNos'

选择UNION ALL而不是UNION,可以避免UNION的重复数据删除开销。

最终结果是,只有一个或其他子查询将包含任何给定部分的任何结果,并且每个子查询可以使用不同的索引来优化资源利用率。

  • 以更长的代码为代价

可能还有其他更好的答案,但这是可行的。

SELECT  COALESCE(m1.`seriesYear`, m2.`seriesYear`) AS seriesYear, 
COALESCE(m1.`modelDesc`, m2.`modelDesc`) AS modelDesc, 
COALESCE(m1.`bodyNo`, m2.`chassisNo`) AS bodyNo 
FROM parts_parsed p
LEFT JOIN parts_modelno m1 ON p.`modelNo` = m1.`chassisNo` 
LEFT JOIN parts_modelno m2 ON p.`bodyNo` = m2.`bodyNo` 
WHERE p.`partNo` = '$PartNos'

为什么不直接使用coalesce来连接呢?

LEFT JOIN parts_modelno m ON p.modelNo = coalesce(m.bodyNo, m.chassisNo)

最新更新