在查询中,是否可以有条件地选择要使用的连接?在下面的查询中,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
永远不会同时具有bodyNo
和modelNo
填充。如果可能的话,你需要用一个你想要的行为的例子来更新这个问题。
编辑:
如果性能很重要(它应该,即使你只意味着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)