我有两张桌子A和B. 表A包含列:ID和POST 表B包含列:ID,POST_ID和UPPERS
我想选择a.POST与正则表达式匹配的所有记录
'\\[cd(i|b)?(=[a-z0-9]+)?\\].+\\[/cd(i|b)?\\]'
和JOIN表B在a.ID = b.POST_ID上,其中b.UPPERS与正则表达式匹配
'(\\|[0-9]+\\![0-9]{4}[-]+[0-9]{2}[-]+[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},){1,}'
我想出了以下语句,但即使列包含与正则表达式匹配的内容,它也不返回任何行
SELECT a.*,b.*
FROM a JOIN
b
ON b.POST_ID=a.ID
WHERE a.POST RLIKE '\\[cd(i|b)?(=[a-z0-9]+)?\\].+\\[/cd(i|b)?\\]' AND
b.UPPERS REGEXP '(\\|[0-9]+\\![0-9]{4}[-]+[0-9]{2}[-]+[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},){1,}'
要点:
我想选择用户发送了与此正则表达式匹配的内容的记录
'\\[cd(i|b)?(=[a-z0-9]+)?\\].+\\[/cd(i|b)?\\]'
然后检查该帖子是否已使用正则表达式
收到至少两个ups(或喜欢)'(\\|[0-9]+\\![0-9]{4}[-]+[0-9]{2}[-]+[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},){2,}'
可以简单地分解:
a prefix pipe: |
a user id: [0-9]+
an exclamation mark: !
a datetime: [0-9]{4}[-]+[0-9]{2}[-]+[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}
and a sufix: ,
NOTE: {2,} simply to check how many times the match occurs
请有人指出我正确的方向是错误的。
样本表数据:
Table A
ID | POST
23 match found [cd=plain]6h+#gtyr[/cd]
24 match found [cd]65#%gte2!iu[/cd]
25 match found [cdi]*tre&y^g82u[/cdi]
26 no match found *tre&y^g82u
27 no match found rtyure99
28 match found [cdb]aha87ulchr[/cdb]
Table B
ID | POST_ID | UPPERS
4 24 |98!2018-02-10 22:43:03,
|35!2018-02-08 20:42:09,
|3!2018-02-05 02:05:07,
5 26 |2!2018-02-10 22:43:03,
|30!2018-02-08 20:42:09,
6 25 |21!2018-02-10 22:43:03,
7 27 |23!2018-02-10 22:43:03,
|11!2018-02-08 20:42:09,
注意:表B中的POST_ID是引用表A的ID的外键
答案 0 :(得分:0)
如果你不介意,我实际上会回答你实际问题背后的问题。我确信我们可以解决为什么正则表达式没有按预期工作,但它引出了一个问题:为什么要使用正则表达式来完成这么简单的任务?
人们首先使用数据库来存储与代码中出现的格式相同的内容。但如果你花一点时间以有意义的方式分解你的数据,你就可以从简陋的MySQL中释放出大量的力量。
考虑一下您希望此查询回答的问题:
正如您已经意识到的那样,这表示有两个表 - 一个用于存储有关帖子的信息,另一个用于存储有关谁将其提升的信息。为了使您的查询变得快速而简单,请考虑在where子句中显示哪些信息属性。
您想要某些标记所包含的帖子。为了提高搜索效率,请将标记标记放在自己的列中:
CREATE TABLE `posts` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`tag` enum('cd','cdi','cdb') DEFAULT NULL,
`tag_value` varchar(11) DEFAULT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
对于您在上面列出的数据,该表可能类似于:
+-----+------+-----------+-------------+
| id | tag | tag_value | content |
+-----+------+-----------+-------------+
| 23 | cd | plain | 6h+#gtyr |
| 24 | cd | NULL | 65#%gte2!iu |
| 25 | cdi | NULL | *tre&y^g82u |
| 26 | NULL | NULL | *tre&y^g82u |
| 27 | NULL | NULL | rtyure99 |
| 28 | cdb | NULL | aha87ulchr |
+-----+------+-----------+-------------+
将数据输入需要更多的工作(这是你创建INSERT
时更好地应用你的正则表达式权力的地方),但现在你可以很容易地用它来做各种各样的事情。我在tag
列中使用了ENUM,因为搜索速度非常快。如果你有大量的标签或者不知道它们将会是什么,你可以改用VARCHAR。
那么如何跟踪UPPERS
?那部分变得非常简单。你需要的只是一个表,每当有人举起一些东西时就会有一行:
CREATE TABLE `uppers` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`post_id` int(11) DEFAULT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
目前,当有人举起某些内容时,您必须找到相关记录,向其添加新数据,然后将其保存回来。现在你可以将记录打到表中。时间将自动设定;您需要插入的只有user_id
和post_id
。您的部分数据可能如下所示:
+----+---------+---------+---------------------+
| id | user_id | post_id | time |
+----+---------+---------+---------------------+
| 2 | 98 | 24 | 2018-02-10 15:23:03 |
| 3 | 35 | 24 | 2018-02-10 15:23:23 |
| 4 | 27 | 24 | 2018-02-10 15:23:43 |
| 5 | 2 | 26 | 2018-02-10 15:24:16 |
| 6 | 30 | 26 | 2018-02-10 15:24:28 |
+----+---------+---------+---------------------+
现在,您可以利用MySQL引擎的强大功能来捕获所需的所有信息:
所有包含所需标签的帖子:
SELECT * FROM posts where tag IN ('cd', 'cdi', 'cdb')
所有帖子都带有所需的标签,至少有一个:
SELECT posts.*, uppers.user_id, uppers.time
FROM posts
INNER JOIN uppers ON posts.id = uppers.post_id
WHERE tag IN ('cd', 'cdi', 'cdb')
这将为每个后上组合返回一行。 INNER JOIN
表示它不会返回任何在uppers表中没有匹配的帖子。这可能是您正在寻找的,但如果您想通过帖子ID将这些组合在一起,您可以让MySQL为您分组:
SELECT posts.*, COUNT(uppers.user_id)
FROM posts
INNER JOIN uppers
WHERE tag IN ('cd', 'cdi', 'cdb')
GROUP BY posts.id
如果您想排除同一用户的重复上传,您只需为每个帖子轻松计算唯一的用户ID:
SELECT posts.*, COUNT(DISTINCT uppers.user_id)
FROM posts
INNER JOIN uppers
WHERE tag IN ('cd', 'cdi', 'cdb')
GROUP BY posts.id
您可以使用许多功能,例如COUNT()
来处理组合在一起的数据。您可以使用MAX(uppers.time)来获取该帖子的最新时间,或者您可以使用GROUP_CONCAT()
之类的函数将值放在一个长字符串中。
最底层的是,通过将数据分解为基本部分,您可以让MySQL(或任何其他关系数据库)更有效地工作,生活变得更加容易。