如何对子查询的结果使用正则表达式?
How to use regexp on the results of a sub query?
我有两个table。
用户
其中有 id 和 phone number
id phone_no
1 ---- 9912678
2 ---- 9912323
3 ---- 9912366
入场 Table ,其中有 id phone number
id phone_no
6 --- 991267823
7 --- 991236621
8 --- 435443455
9 --- 243344333
我想找到所有 phone 编号 的 Admission's table 与 users table 和 update 它在 users table.
所以我正在尝试这个
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}')
但我收到此错误 子查询 returns 多于 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
table 以查看是否有 exists
任何 phone_no
符合我们当前正在查看的录取编号标准。
没关系正则表达式。使用 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%'
仅当 admission
table、user
table 中存在重复数字时才需要 distinct
关键字].否则可以省略。
尝试以下查询之一:
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]+$'
如果"trailing digits"个数不固定,也可以用:
LIKE concat(u.phone_no, '%')
或
REGEXP concat('^', u.phone_no, '[0-9]*$')
但在这种情况下,如果 users.phone_no
可能是另一个 users.phone_no
的子序列(例如 99123 和 991234),您可能需要使用 SELECT DISTICT a.phone_no
。
更新
在 运行 一些针对用户的 10K 行 table 和 100K 行的入场测试 table 之后,我得到了以下查询:
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 条件。但在更大的 tables 上,查询可能会超时。使用 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 检查相结合。
我有两个table。
用户 其中有 id 和 phone number
id phone_no
1 ---- 9912678
2 ---- 9912323
3 ---- 9912366
入场 Table ,其中有 id phone number
id phone_no
6 --- 991267823
7 --- 991236621
8 --- 435443455
9 --- 243344333
我想找到所有 phone 编号 的 Admission's table 与 users table 和 update 它在 users table.
所以我正在尝试这个
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}')
但我收到此错误 子查询 returns 多于 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
table 以查看是否有 exists
任何 phone_no
符合我们当前正在查看的录取编号标准。
没关系正则表达式。使用 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%'
仅当 admission
table、user
table 中存在重复数字时才需要 distinct
关键字].否则可以省略。
尝试以下查询之一:
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]+$'
如果"trailing digits"个数不固定,也可以用:
LIKE concat(u.phone_no, '%')
或
REGEXP concat('^', u.phone_no, '[0-9]*$')
但在这种情况下,如果 users.phone_no
可能是另一个 users.phone_no
的子序列(例如 99123 和 991234),您可能需要使用 SELECT DISTICT a.phone_no
。
更新
在 运行 一些针对用户的 10K 行 table 和 100K 行的入场测试 table 之后,我得到了以下查询:
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 条件。但在更大的 tables 上,查询可能会超时。使用 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 检查相结合。