我有下表
+-------+-------+-------+
| ID | Name1 | Name2 |
+-------+-------+-------+
| 1| Steve | Steven| - true
| 1| Steven| Steve | - true
| 1| Max | Steve | - false
| 1| Steve | Steve | - true
+-------+-------+-------+
我需要确定行Name1
以Name2
开头或Name2
以Name1
开头
问题:
是否有比Name2 LIKE Concat(Name1, '%') OR Name1 LIKE Concat(Name2, '%')
这个例子有点简化,因为Name1
是一个巨大的子选择,像Concat(Name1, '%') LIKE Concat(Name2, '%')
之类的东西会大大增加我的应用程序的性能
更新
指出我的问题,完整的选择看起来像
(SELECT Name FROM User JOIN UserGroup ON User.UserID = UserGroup.UserID JOIN Company ON Company.UserID = User.UserID WHERE UserGroup.Range > 2 AND User.Create > '2010-01-01' AND Company.Country = 'CH' ORDER BY User.StartDate DESC LIMIT 1) AS Name2
所以上面的陈述看起来像是
(SELECT Name FROM User JOIN UserGroup ON User.UserID = UserGroup.UserID JOIN Company ON Company.UserID = User.UserID WHERE UserGroup.Range > 2 AND User.Create > '2010-01-01' AND Company.Country = 'CH' ORDER BY User.StartDate DESC LIMIT 1) LIKE Concat(Name1, '%') OR Name1 LIKE Concat((SELECT Name FROM User JOIN UserGroup ON User.UserID = UserGroup.UserID JOIN Company ON Company.UserID = User.UserID WHERE UserGroup.Range > 2 AND User.Create > '2010-01-01' AND Company.Country = 'CH' ORDER BY User.StartDate DESC LIMIT 1), '%')
并且select被调用两次 - 必须有一种从数据库中只获取Name2
一次的方法
答案 0 :(得分:1)
也许更快:
select *
from table1
WHERE substring(name2,1,length(name1))=name1
答案 1 :(得分:1)
正如其他人评论的那样,你的方法很好。但是有一种方法可以用相等的OR
和两个LIKE
子句来编写它。我们的想法是取两个名称的最小长度,将两个名称截断为该长度,然后进行比较。
select *,
LEFT(Name1, LEAST(LENGTH(Name1), LENGTH(Name2))) =
LEFT(Name2, LEAST(LENGTH(Name1), LENGTH(Name2)))
from Table1
这可能更有效,只需避免OR和LIKE。虽然阅读比较麻烦,但你说它需要与另一个复杂的表达式相结合......要清理它,你可以将比较逻辑放入存储的函数中。
**更新**我在更新的示例中看到,Name2实际上是一个嵌套的SELECT,并且您不会运行它2或3次。
您可以使用嵌套查询。内部查询构建一个行表,看起来就像原始问题的简化示例。类似的东西:
SELECT ID, Name1,
(SELECT Name FROM User JOIN UserGroup ON User.UserID = UserGroup.UserID JOIN Company ON Company.UserID = User.UserID WHERE UserGroup.Range > 2 AND User.Create > '2010-01-01' AND Company.Country = 'CH' ORDER BY User.StartDate DESC LIMIT 1) AS Name2
FROM Table1
现在说出这个"表" PotentialMatch,并使用外部查询来包装它,以获取匹配的行。类似的东西:
SELECT PotentialMatch.ID, PotentialMatch.Name1 FROM
(SELECT ID, Name1,
(SELECT Name FROM User JOIN UserGroup ON User.UserID = UserGroup.UserID JOIN Company ON Company.UserID = User.UserID WHERE UserGroup.Range > 2 AND User.Create > '2010-01-01' AND Company.Country = 'CH' ORDER BY User.StartDate DESC LIMIT 1) AS Name2
FROM Table1) PotentialMatch
WHERE LEFT(PotentialMatch.Name1, LEAST(LENGTH(PotentialMatch.Name1), LENGTH(PotentialMatch.Name2))) =
LEFT(PotentialMatch.Name2, LEAST(LENGTH(PotentialMatch.Name1), LENGTH(PotentialMatch.Name2)))
或者,如果您愿意,您可以使用此子查询技术与原始LIKE
比较一样:
SELECT PotentialMatch.ID, PotentialMatch.Name1 FROM
(SELECT ID, Name1,
(SELECT Name FROM User JOIN UserGroup ON User.UserID = UserGroup.UserID JOIN Company ON Company.UserID = User.UserID WHERE UserGroup.Range > 2 AND User.Create > '2010-01-01' AND Company.Country = 'CH' ORDER BY User.StartDate DESC LIMIT 1) AS Name2
FROM Table1) PotentialMatch
WHERE PotentialMatch.Name1 LIKE CONCAT(PotentialMatch.Name2, '%')
OR PotentialMatch.Name2 LIKE CONCAT(PotentialMatch.Name1, '%')
如果没有SQLFiddle,我无法测试这些,但希望你能得到这个想法。
答案 2 :(得分:1)
试试这个:
SELECT *
FROM table1
WHERE Name2 REGEXP Name1;
或者两个方向都这样做:
SELECT *
FROM table1
WHERE (
CASE WHEN (SELECT Name2 REGEXP Name1) = 0 THEN
0 ELSE
(SELECT Name1 REGEXP Name2)
END) = 0;