在我的查询中,我需要有几个正则表达式来过滤用户名或电子邮件,因为我对它们并不感兴趣。所以,我已经在mysql中编写了这个查询,运行之后,花了这么多时间才给我回复结果。我的机智表现有问题。此外,运行此查询后,甚至不会以正确的方式过滤我的信息。我不确定如何改进我的查询以便:
我将不胜感激任何帮助。
select DISTINCT t.user, vg_product_id,t.`platform`, pd.`mail`,
substring_index(group_concat(p.ts ORDER BY p.ts DESC SEPARATOR ','), ',', 1) as sub_start_ts,
substring_index(group_concat(t.`expires_at`ORDER BY t.`expires_at` DESC SEPARATOR ','), ',', 1) as expired_time
from users u
inner join tariff_subs_info t on (t.`user` = u.`user_xmpp_login`
and t.`user` NOT REGEXP ('^([A-Za-z]{2,3}(produsero|usero)+[0-9]{1,3})$' or '(\w+|\d+)?test(\w+|\d+)?' )
and t.vg_product_id REGEXP "^(europe?|usa?|unlimited?|basic?)([a-zA-Z0-9]+|\_)+(and?|ios?)+$" )
left join plus_data pd on (u.`user_xmpp_login` = pd.`user`)
inner join purchase_log p on (p.purchase_id = t.purchase_id)
WHERE (pd.mail not like '%guerrillamail.com'
or pd.mail is null)
group by 1,2 ORDER BY DATE(p.ts);
这是我的结果:
noadstestuser basic_XXX_ios ios NULL 2015-10-26 14:00:32 2015-10-26 14:05:24
brusero2 unlimited_XX_ios ios brusero2@yhx.yg 2015-11-03 15:41:57 2015-11-03 15:46:45
brusero3 bXX_uscios ios brusero3@tb.fff 2015-11-03 15:43:53 2015-11-03 15:48:42
esusero1 unliXX_usc ios esusero1@es.userr 2015-11-03 13:51:54 2015-11-03 13:56:41
esusero3 basic_X_i os esusero3@yn.yyf 2015-11-03 13:55:08 2015-11-03 14:00:02
esusero4 basic_X ios esusero4@yn.ttx 2015-11-03 14:01:50 2015-11-03 14:06:38
esusero5 unXXXed_us ios esusero5@uh.hhb 2015-11-03 14:45:38 2015-11-03 14:50:24
esusero6 basic_XX ios esusero6@yh.hvv 2015-11-03 14:51:22 2015-11-03 14:56:09
esusero7 unlimXX_ ios esusero7@yh.yyh 2015-11-03 15:20:35 2015-11-03 15:25:24
esusero8 basXX_usc ios esusero8@ij.iih 2015-11-03 15:22:29 2015-11-03 15:27:14
flusero2 unlXXXe ios flusero2@yh.yog 2015-11-03 16:57:58 2015-11-03 17:02:45
nlprodusero1 baXicXX_X ios nlprodusero1@yh.rof 2015-11-03 14:06:52 2015-11-03 14:11:44
nlprodusero2 unliXXXeds ios nlprodusero2@uoh.df 2015-11-03 14:08:28 2015-11-03 14:13:16
prodpurchasetest baXXc_usXc ios NULL 2015-11-03 09:20:51 2015-11-03 09:25:41
ukusero1 basicXXsca ios ukusero1@uj.uoh 2015-11-03 15:45:59 2015-11-03 15:48:42
ukusero2 baXXsca ios gbuser@yb.jov 2015-11-03 17:00:14 2015-11-03 17:05:07
ukusero4 unlXXd_usc ios ukusero4@uoh.jv 2015-11-03 17:02:10 2015-11-03 17:02:45
usprodusero1 uXXited_us ios usprodusero1@ook.ok 2015-11-03 13:30:25 2015-11-03 13:35:14
usprodusero2 bXXXs ios usprodusero2@ok.iob 2015-11-03 13:33:39 2015-11-03 13:38:31
usprodusero5 unlXXsc ios usprodusero5@rou.tf 2015-11-03 15:34:35 2015-11-03 15:39:26
这个结果让我意外,我不想拥有它们。尽管使用了NOT REGEXP
,但所有这些都是我的结果。我该如何解决这些问题?
编辑后:
select t.user, vg_product_id,t.`platform`, pd.`mail`,
substring_index(group_concat(p.ts ORDER BY p.ts DESC SEPARATOR ','), ',', 1) as sub_start_ts,
substring_index(group_concat(t.`expires_at`ORDER BY t.`expires_at` DESC SEPARATOR ','), ',', 1) as expired_time
from users u
inner join tariff_subs_info t on (t.`user` = u.`user_xmpp_login`
and t.`user` NOT REGEXP ('^([A-Za-z]{2,3}(produsero|usero)+[0-9]{1,3})$')
and t.`user` NOT REGEXP ('test')
and t.vg_product_id REGEXP ("^(europe?|usa?|unlimited?|basic?)([a-zA-Z0-9_]+)+(and?|ios?)+$" ))
left join plus_data pd on (u.`user_xmpp_login` = pd.`user`)
inner join purchase_log p on (p.purchase_id = t.purchase_id)
WHERE (pd.mail not like '%guerrillamail.com'
and pd.mail NOT LIKE '%test%'
or pd.mail is null)
group by 1,2 ORDER BY DATE(p.ts);
我仍然有以下结果,并且'测试'在我的用户中。
noadstestuser basixxxf_ios ios NULL 2015-10-26 14:00:32 2015-10-26 14:05:24
prodpurchasetest basic_uscaxxs ios NULL 2015-11-03 09:20:51 2015-11-03 09:25:41
esusertest basic_uscxxxs ios esusertest@ixn.ib 2015-11-04 13:53:48 2015-11-04 13:58:44
esusertest2 basic_uxxxx ios esusertedt2@iu.ycx 2015-11-04 14:11:12 2015-11-04 14:13:44
答案 0 :(得分:4)
MySQL REGEXP不支持\w
和\d
速记字符类。因此,(\w+|\d+)?
子模式在MySQL中无效。由于?
量词使子模式可选(重复一次或零次),因此可以完全删除它们。
因此,or '(\w+|\d+)?test(\w+|\d+)?'
将变为and t.`user` NOT REGEXP ('test')
,但其含义与and t.`user` NOT LIKE '%test%'
相同。
接下来,([a-zA-Z0-9]+|\_)+
也很成问题,因为有一个嵌套量词(一个+
在一个交替组内,其中应用了另一个+
量词。这是可能发生灾难性回溯的经典场景。我建议用[a-zA-Z0-9_]+
替换此子模式以匹配字母,数字或下划线。或其等效的[[:alnum:]_]+
。
答案 1 :(得分:1)
首先关闭:
t.`user` NOT REGEXP (
'usero pattern' or
'test pattern'
)
不正确..你不能or
两个字符串输入..你需要:
t.`user` NOT REGEXP ('usero pattern')
AND t.`user` NOT REGEXP ('test pattern')
您应该首先直接在相关表上测试所有表达式,以确保逻辑存在..如@WiktorStribizew所述,字和数字字符集可能无法识别。
接下来我猜你在查询中不需要DISTINCT和GROUP BY,你可以放弃DISTINCT。
不幸的是,你的正则表达式会击中每一行......你可以做很多事情。
如果这是一次性查询,你可能只需要花时间。你可能应该运行一个EXPLAIN来检查没有发生任何疯狂的事情,但确定。
如果您定期运行查询,我建议您在保存行时通过应用程序拆分相关信息,然后索引生成的额外列,它不会被标准化..但它可能是性能的情况提升将使它值得。
<强>更新强>
例如,前两行可以保存为:
[user:'noadstestuser', is_usero:0, is_test:1],
[user:'brusero2', is_usero:1, is_test:0]
然后你的
t.`user` NOT REGEXP ('usero pattern')
AND t.`user` NOT REGEXP ('test pattern')
变得简单
t.is_usero = 0 AND t.is_test = 0
快得多..如果有帮助,你可以索引这些字段。
当然,在保存每一行之前,您必须进行匹配,这可能更容易使用您的应用程序逻辑(例如PHP代码)。