SQL 正则表达式和字段

Posted

技术标签:

【中文标题】SQL 正则表达式和字段【英文标题】:SQL regex and field 【发布时间】:2013-06-09 05:32:35 【问题描述】:

我想更改查询以返回 extra_fields 中的乘法值,如何更改正则表达式?我也不明白extra_fields 是什么——它是一个字段吗?如果是这样,为什么不使用 i.extra_fields 之类的表前缀调用它?

SELECT i.*,
    CASE WHEN i.modified = 0 THEN i.created ELSE i.modified END AS lastChanged,
    c.name AS categoryname,
    c.id AS categoryid,
    c.alias AS categoryalias,
    c.params AS categoryparams
FROM #__k2_items AS i
LEFT JOIN #__k2_categories AS c ON c.id = i.catid
WHERE i.published = 1
    AND i.access IN(1,1)
    AND i.trash = 0
    AND c.published = 1
    AND c.access IN(1,1)
    AND c.trash = 0
    AND (i.publish_up = '0000-00-00 00:00:00'
        OR i.publish_up <= '2013-06-12 22:45:19'
    )
    AND (i.publish_down = '0000-00-00 00:00:00'
        OR i.publish_down >= '2013-06-12 22:45:19'
    )
    AND extra_fields REGEXP BINARY '(.*"id":"2","value":\["[^\"]*1[^\"]*","[^\"]*2[^\"]*","[^\"]*3[^\"]*"\].*)'
ORDER BY i.id DESC

【问题讨论】:

你试过转义正则表达式中的大括号吗? 这不是答案,而是评论 【参考方案1】:

extra_fields#__k2_items 表的一列。表限定符可以省略,因为它在此查询中没有歧义。该列是 JSON 编码的。这是一种序列化格式,用于存储设计上不可搜索的信息。应用正则表达式可能有一天会奏效,但另一天会失败,因为不能保证 id 先于 value(如您的示例所示)。

正确的方法

过滤此问题的正确方法是忽略 SQL 查询中的 extra_fields 条件,而是在结果集中进行评估。示例:

$rows = $db->loadObjectList('id');
foreach ($rows as $id => $row) 
    $extra_fields = json_decode($row->extra_fields);
    if ($extra_fields->id != 2) 
         unset($rows[$id]);
    

捷径

如果您无法更改数据库布局(对于您希望保持可更新的扩展来说确实如此),您必须将条件一分为二,因为无法保证 em> 用于子字段的特定顺序。出于某种原因,value 的某一天可能会发生在之前id。因此,将您的查询更改为

...
AND extra_fields LIKE '%"id":"2"%' 
AND extra_fields REGEXP BINARY '"value":\[("[^\"]*[123][^\"]*",?)+\]'

【讨论】:

我更喜欢保留 sql 因为有分页。无论如何我想把这个 REGEXP BINARY '(.*"id":"2","value":["[^\"]*1[^\"]*","[^\"]*2 [^\"]*","[^\"]*3[^\"]*"].*)' 找到其中一个值而不是精确的短语 好吧,那么 K2 是错误的选择。正如我在回答中所说,序列化的字段按设计是不可搜索的。 更新了我的答案以使extra_fields 有点可搜索。【参考方案2】:

准备一个中间表来保存 extra_fields 的内容。每个 extra_fields 字段都会被转换成一系列记录。然后做一个连接。 创建触发器和 cronjob 以保持临时表同步。

另一种方法是在 Perl 中编写 UDF 来解码字段,但 AFAIK 它在 mysql 中不可索引。

使用外部搜索引擎超出范围。

【讨论】:

【参考方案3】:

好的,我不想更改数据库结构,我得到了一些帮助并将正则表达式更改为AND extra_fields REGEXP BINARY '(.*"id":"2","value":\[("[^\"]*[123][^\"]*",?)+\].*)' 我得到了正确的结果 谢谢

【讨论】:

以上是关于SQL 正则表达式和字段的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL 查询中的正则表达式 - 仅限数字和句点

如何利用oracle正则表达式去除字段中含有的汉字

以 7 位数字结尾的字段的 Big Query SQL 正则表达式

在 Oracle SQL 中使用正则表达式在字符串字段中查找 Unicode 字符

mysql 正则表达式求解答

正则表达式 '\b' 的 T-SQL 等效项