我有两张桌子。
用户 其中 ID 和电话号码
id phone_no
1 ---- 9912678
2 ---- 9912323
3 ---- 9912366
入场表, ID 电话号码
id phone_no
6 --- 991267823
7 --- 991236621
8 --- 435443455
9 --- 243344333
我想找到与用户表具有相同模式且更新的入场表的所有电话号码 >它在用户表中。
所以我正在尝试这个
select phone_no from admission where phone_no REGEXP (SELECT phone_no
FROM `users` AS user
WHERE user.phone_no REGEXP '^(99)+[0-9]{8}')
但我收到此错误子查询返回超过1行
寻求帮助。
答案 0 :(得分:1)
我认为这可以做你想要的,我做了一些改进(SQLfiddle):
select * from admission a where exists (
select * from (
select substr(phone_no, 1, 7) pn from users where phone_no REGEXP '^99[0-9]{5}'
) o where a.phone_no like concat(o.pn, '%')
)
我必须修改正则表达式以获得任何匹配。如果长度固定,则可以使用like
轻松完成第二次检查。我们会查看user
表格,看看exists
是否phone_no
符合我们目前正在查看的录取号码标准。{/ p>
答案 1 :(得分:1)
别介意正则表达式。使用like
select distinct a.phone_no
from user u
join admission a on a.phone_no like concat(u.phone_no, '%')
where u.phone_no like '99%'
仅当distinct
表和/或admission
表中存在重复的数字时,才需要user
关键字。否则,可以省略。
答案 2 :(得分:1)
尝试其中一个查询:
SELECT a.phone_no
FROM admission a
JOIN users u on a.phone_no LIKE concat(u.phone_no, '__')
WHERE u.phone_no REGEXP '^(99)+[0-9]+$'
或
SELECT a.phone_no
FROM admission a
JOIN users u on a.phone_no REGEXP concat('^', u.phone_no, '[0-9]{2}$')
WHERE u.phone_no REGEXP '^(99)+[0-9]+$'
如果“固定数字”的数量不固定,您也可以使用:
LIKE concat(u.phone_no, '%')
或
REGEXP concat('^', u.phone_no, '[0-9]*$')
但在这种情况下,如果SELECT DISTICT a.phone_no
可能是其他users.phone_no
的子序列(例如99123和991234),则可能需要使用users.phone_no
。
<强>更新强>
运行一些测试,其中10K行为用户表,100K行为准入表,我来到以下查询:
SELECT a.phone_no
FROM admission a
JOIN users u
ON a.phone_no >= u.phone_no
AND a.phone_no < CONCAT(u.phone_no, 'z')
AND a.phone_no LIKE CONCAT(u.phone_no, '%')
AND a.phone_no REGEXP CONCAT('^', u.phone_no, '[0-9]*$')
WHERE u.phone_no LIKE '99%'
AND u.phone_no REGEXP '^(99)+[0-9]*$'
UNION SELECT 0 FROM (SELECT 0) dummy WHERE 0
这样您就可以使用REGEXP
并且仍然可以获得出色的效果。此查询几乎立即在我的测试用例中执行。
逻辑上,您只需要REGEXP条件。但是在更大的表上,查询可能会超时。使用LIKE条件将在REGEXP检查之前过滤结果集。但即使使用LIKE查询也不是很好。出于某种原因,MySQL不对连接使用范围检查。所以我添加了一个明确的范围检查:
ON a.phone_no >= u.phone_no
AND a.phone_no < CONCAT(u.phone_no, 'z')
通过此检查,您可以从JOIN部分中删除LIKE条件。
UNION部分是DISTICT的替代品。 MySQL似乎将DISTINCT转换为GROUP BY语句,该语句表现不佳。使用带有空结果集的UNION,强制MySQL在SELECT之后删除重复项。如果使用固定数量的尾随数字,则可以删除该行。
您可以根据需要调整REGEXP模式:
...
AND a.phone_no REGEXP CONCAT('^', u.phone_no, '[0-9]{2}$')
...
AND u.phone_no REGEXP '^(99)+[0-9]{8}$'
...
如果您只需要REGEXP来检查phone_no的长度,您也可以使用带有'_'占位符的LIKE条件。
AND a.phone_no LIKE CONCAT(u.phone_no, '__')
...
AND u.phone_no LIKE '99________$'
或将LIKE条件与STR_LENGTH检查结合起来。