【问题标题】:How to select the word which is matched by regexp in sql?如何在sql中选择正则表达式匹配的单词?
【发布时间】:2017-10-04 13:02:44
【问题描述】:

我正在尝试使用 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

我怎样才能做到这一点。

感谢您的帮助。

【问题讨论】:

标签: mysql sql


【解决方案1】:

创建表格/插入数据

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. 您确实应该有一个存储主题标签的表格。

【讨论】:

  • 嘿伙计,谢谢你的回答。它真的很有帮助。但正如你所说,还有另一条评论。我认为我真的应该将主题标签存储在其他表中。所以我正在考虑帖子和主题标签之间的“多对多关系”。我应该这样做吗?顺便说一句,你的回答真的很有帮助,谢谢。
  • @aary trivedi 没问题.. 它可能是多对多关系,但取决于您的需求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-05
  • 1970-01-01
  • 2016-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多