mysql - 如何在sql中选择regexp匹配的单词?

标签 mysql sql

我正在尝试在 sql 中使用 REGEXP 从字段中提取主题标签。现在我正在执行此查询

SELECT caption FROM posts WHERE caption REGEXP "#[a-zA-Z0-9_]+"

但我想提取与此模式匹配的特定单词。

就像我的数据库中有以下条目

id caption         user
1  #hi i'm here    2
2  hello #hi there 3
3  i'm x #hi       4
4  I'm #Driving    2
5  I #love #food   6

现在我的查询正在返回

caption
#hi i'm here
hello #hi there
i'm x #hi
I'm #Driving
I #love #food

但我想要

tag
#hi
#Driving
#love
#food

我怎样才能实现这个目标。

感谢您的帮助。

最佳答案

创建表/插入数据

CREATE TABLE Table1
    (`id` INT, `caption` VARCHAR(255), `user` INT)
;

INSERT INTO Table1
    (`id`, `caption`, `user`)
VALUES
    (1, '#hi i''m here', 2),
    (2, 'hello #hi there', 3),
    (3, 'i''m x #hi', 4),
    (4, 'I''m #Driving', 2),
    (5, 'I #love #food', 6)
;

您可以使用 SUBSTRING_INDEX(SUBSTRING_INDEX(caption, ' ', 1), ' ', -1) 拆分标题中的单词以获取第一个单词 SUBSTRING_INDEX(SUBSTRING_INDEX(caption, ' ', 2), ' ', -1) 获取第二个单词。

但是如何使其动态化,以便可以拆分更多的单词。

首先,您使用 SQL 制作一个数字生成器。 此查询将生成一个从 1 到 100 的数字列表

查询

SELECT
  @number := @number + 1 AS number
FROM (
  (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) row1
  CROSS JOIN
  (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) row2
  CROSS JOIN 
  (SELECT @number:=0) AS init_user_params
)  

结果

number  
--------
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      ...
      ...
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
     100

现在我们可以将生成的数字列表与 Table1 交叉连接(在我们的示例中) 这将生成 (表计数) * 100 条具有重复记录的记录。 并在 SUBSTRING_INDEX(SUBSTRING_INDEX(caption, ' ', [word offset]), ' ', -1) 中使用生成的数字列表,如下所示

查询

SELECT  
  DISTINCT #remove duplicates
    SUBSTRING_INDEX(SUBSTRING_INDEX(caption, ' ', numbers.number), ' ', -1) AS tag
FROM (

  SELECT
    @number := @number + 1 AS number
  FROM (
    (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) row1
     CROSS JOIN
    (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) row2
     CROSS JOIN 
    (SELECT @number:=0) AS init_user_params
  )  
) 
 AS numbers
CROSS JOIN Table1
WHERE
 SUBSTRING_INDEX(SUBSTRING_INDEX(caption, ' ', numbers.number), ' ', -1) LIKE '#%' #we only want words starting with #
ORDER BY 
 Table1.id ASC 

结果

tag       
----------
#hi       
#Driving  
#love     
#food     

注释

  1. 此查询仅在标题等于或少于 100 个单词时有效
  2. 此查询在较小尺寸的表上相当快。在较大的表上,这不会很好地扩展,因为没有 CROSS JOIN
  3. 您确实应该有一个表来存储主题标签。

关于mysql - 如何在sql中选择regexp匹配的单词?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46565606/

相关文章:

MySQL 通过连接进行更新

mysql - MariaDB 使用 utf8mb4 时出现错误

mysql - 获取一列的最小值和最大值以及所有行数据

python - 如何将字符串转换为数组并连接到sql中的另一个表

java - 将 sql varchar 分配给 JLabel 值

php - PDO 和 SQL IN 语句

mysql搜索表名的段

mysql - 与 SQL Source Control、SQL Automation Pack 和 Jenkins 的持续集成

sqlalchemy 对称多对一友谊

php - 使用 Ajax 插入 mysql 数据库的问题