您似乎要检查的主要内容是带有前导 % 的姓氏。这会使该列上的索引无用,并且您的 SQL 正在搜索它两次。
我不是 100% 确定你想要做什么。您的 SQL 似乎将所有名称匹配的成员与所需的成员相匹配,然后获取这些成员的最后一个 registration_history 记录。你得到的可能来自任何一个匹配的成员,这似乎很奇怪,除非你只期望得到一个成员。
如果是这种情况,下面的小整理(删除和 IN 并将其更改为 JOIN)可能会稍微改善一些事情。
SELECT
COALESCE(NULLIF(Registration_History.RegYear, ''), NULLIF(Registration.Year, '')) AS RegYear,
COALESCE(NULLIF(Registration_History.RegNumber, ''), NULLIF(Registration.RegNumber, ''), NULLIF(Member.MemberID, '')) AS RegNumber,
Member.MemberID,
Member.LastName,
Member.FirstName,
CASE
WHEN Member.LastNameTrimmed = :LastName
THEN 1
WHEN Member.LastNameTrimmed LIKE CONCAT(:LastName, '%')
THEN 2
ELSE 3
END AS Relevance
FROM Member
LEFT JOIN Registration_History FORCE INDEX (PRIMARY)
ON Registration_History.rehiId =
(
SELECT RHSubSelect.rehiId
FROM Registration_History AS RHSubSelect
INNER JOIN Member
ON RHSubSelect.MemberID = Member.MemberID
WHERE Member.LastName LIKE CONCAT('%', :LastName, '%')
ORDER BY RHSubSelect.EffectiveDate DESC
LIMIT 0, 1
)
LEFT JOIN Registration FORCE INDEX(MemberID)
ON Registration.MemberID = Member.MemberID
WHERE Member.LastName LIKE CONCAT('%', :LastName, '%')
GROUP BY Member.MemberID
ORDER BY Relevance ASC,LastName ASC,FirstName asc
LIMIT 0, 1000
但是,如果这不是您想要的,那么可能会进行进一步的更改。
多一点清理,消除一个带有前导通配符的 LIKE:-
SELECT
COALESCE(NULLIF(Sub2.RegYear, ''), NULLIF(Registration.Year, '')) AS RegYear,
COALESCE(NULLIF(Sub2.RegNumber, ''), NULLIF(Registration.RegNumber, ''), NULLIF(Member.MemberID, '')) AS RegNumber,
Member.MemberID,
Member.LastName,
Member.FirstName,
CASE
WHEN Member.LastNameTrimmed = :LastName
THEN 1
WHEN Member.LastNameTrimmed LIKE CONCAT(:LastName, '%')
THEN 2
ELSE 3
END AS Relevance
FROM Member
LEFT OUTER JOIN Registration
ON Registration.MemberID = Member.MemberID
LEFT OUTER JOIN
(
SELECT Registration_History.MemberID, Registration_History.rehiID, Registration_History.RegYear, Registration_History.RegNumber
FROM Registration_History
INNER JOIN
(
SELECT RHSubSelect.MemberID, MAX(RHSubSelect.EffectiveDate) AS EffectiveDate
FROM Registration_History AS RHSubSelect
GROUP BY RHSubSelect.MemberID
) Sub1
ON Registration_History.MemberID = Sub1.MemberID AND Registration_History.EffectiveDate = Sub1.EffectiveDate
) Sub2
ON Sub2.MemberID = Member.MemberID
WHERE Member.LastName LIKE CONCAT('%', :LastName, '%')
GROUP BY Member.MemberID
ORDER BY Relevance ASC,LastName ASC,FirstName asc
LIMIT 0, 1000
这将获取具有匹配名称的所有成员、匹配的注册记录以及具有最新 EffectiveDate 的registration_history 记录。
我不认为最后一个 GROUP BY 是必要的(假设成员和注册之间存在 1 对 1 的关系,如果不是,您可能想要使用 GROUP BY 以外的其他东西),但我现在把它留在了。
害怕没有表声明和一些相同的数据,我无法真正测试它。
编辑 - 有点戏,试图减少它在选择早期处理的数量: -
SELECT
COALESCE(NULLIF(Registration_History.RegYear, ''), NULLIF(Sub1.Year, '')) AS RegYear,
COALESCE(NULLIF(Registration_History.RegNumber, ''), NULLIF(Sub1.RegNumber, ''), NULLIF(Sub1.MemberID, '')) AS RegNumber,
Sub1.MemberID,
Sub1.LastName,
Sub1.FirstName,
CASE
WHEN Sub1.LastName = :LastName
THEN 1
WHEN Sub1.LastName LIKE CONCAT(:LastName, '%')
THEN 2
ELSE 3
END AS Relevance
FROM
(
SELECT
Member.MemberID,
Member.LastName,
Member.FirstName,
Registration.Year,
Registration.RegNumber,
MAX(Registration_History.EffectiveDate) AS EffectiveDate
FROM Member
LEFT OUTER JOIN Registration
ON Registration.MemberID = Member.MemberID
LEFT OUTER JOIN Registration_History
ON Registration_History.MemberID = Member.MemberID
WHERE Member.LastName LIKE CONCAT('%', :LastName, '%')
GROUP BY Member.MemberID,
Member.LastName,
Member.FirstName,
Registration.Year,
Registration.RegNumber
) Sub1
LEFT OUTER JOIN Registration_History
ON Registration_History.MemberID = Sub1.MemberID AND Registration_History.EffectiveDate = Sub1.EffectiveDate
ORDER BY Relevance ASC,LastName ASC,FirstName asc
LIMIT 0, 1000
再次编辑。
试试这个。您正在排序的项目都来自成员表,因此在子选择中尽早排除可能是有意义的。
SELECT
COALESCE(NULLIF(Registration_History2.EffectiveDate, ''), NULLIF(Registration2.Year, '')) AS RegYear,
COALESCE(NULLIF(Registration_History2.RegNumber, ''), NULLIF(Registration2.RegNumber, ''), NULLIF(Member.MemberID, '')) AS RegNumber,
Member.MemberID,
Member.LastName,
Member.FirstName,
Member.Relevance
FROM
(
SELECT Member.MemberID,
Member.LastName,
Member.FirstName,
CASE
WHEN Member.LastName = :LastName
THEN 1
WHEN Member.LastName LIKE CONCAT(:LastName, '%')
THEN 2
ELSE 3
END AS Relevance
FROM Member
WHERE Member.LastName LIKE CONCAT('%', :LastName, '%')
ORDER BY Relevance ASC,LastName ASC,FirstName asc
LIMIT 0, 1000
) Member
LEFT OUTER JOIN
(
SELECT MemberID, MAX(EffectiveDate) AS EffectiveDate
FROM Registration_History
GROUP BY MemberID
) Registration_History
ON Registration_History.MemberID = Member.MemberID
LEFT OUTER JOIN Registration_History Registration_History2
ON Registration_History2.MemberID = Registration_History.MemberID
AND Registration_History2.EffectiveDate = Registration_History.EffectiveDate
LEFT OUTER JOIN
(
SELECT MemberID, MAX(Year) AS Year
FROM Registration
GROUP BY MemberID
) Registration
ON Registration.MemberID = Member.MemberID
LEFT OUTER JOIN
(
SELECT MemberID, Year, MAX(RegNumber) AS RegNumber
FROM Registration
GROUP BY MemberID, Year
) Registration2
ON Registration2.MemberID = Member.MemberID
AND Registration2.Year = Registration.Year
再次编辑
未测试以下内容,因此这更多是为了了解另一种尝试解决问题的方法,使用 GROUP_CONCAT 的小技巧:-
SELECT
COALESCE(NULLIF(Registration_History.EffectiveDate, ''), NULLIF(Registration.Year, '')) AS RegYear,
COALESCE(NULLIF(Registration_History.RegNumber, ''), NULLIF(Registration.RegNumber, ''), NULLIF(Member.MemberID, '')) AS RegNumber,
Member.MemberID,
Member.LastName,
Member.FirstName,
Member.Relevance
FROM
(
SELECT Member.MemberID,
Member.LastName,
Member.FirstName,
CASE
WHEN Member.LastName = :LastName
THEN 1
WHEN Member.LastName LIKE CONCAT(:LastName, '%')
THEN 2
ELSE 3
END AS Relevance
FROM Member
WHERE Member.LastName LIKE CONCAT('%', :LastName, '%')
ORDER BY Relevance ASC,LastName ASC,FirstName asc
LIMIT 0, 1000
) Member
LEFT OUTER JOIN
(
SELECT MemberID,
SUBSTRING_INDEX(GROUP_CONCAT(EffectiveDate ORDER BY EffectiveDate DESC), ",", 1) AS EffectiveDate,
SUBSTRING_INDEX(GROUP_CONCAT(RegNumber ORDER BY EffectiveDate DESC), ",", 1) AS RegNumber
FROM Registration_History
GROUP BY MemberID
) Registration_History
ON Registration_History.MemberID = Member.MemberID
LEFT OUTER JOIN
(
SELECT MemberID,
SUBSTRING_INDEX(GROUP_CONCAT(Year ORDER BY Year DESC), ",", 1) AS Year,
SUBSTRING_INDEX(GROUP_CONCAT(RegNumber ORDER BY Year DESC), ",", 1) AS RegNumber
FROM Registration
GROUP BY MemberID
) Registration
ON Registration.MemberID = Member.MemberID