mySQL从2个方向开始

时间:2016-02-12 13:03:50

标签: mysql sql wildcard sql-like

我有下表

+-------+-------+-------+
|  ID   | Name1 | Name2 |
+-------+-------+-------+
|      1| Steve | Steven| - true
|      1| Steven| Steve | - true
|      1| Max   | Steve | - false
|      1| Steve | Steve | - true
+-------+-------+-------+

我需要确定行Name1Name2开头或Name2Name1开头

问题:

是否有比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一次的方法

3 个答案:

答案 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;