【问题标题】:SQL regex and fieldSQL 正则表达式和字段
【发布时间】: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

【问题讨论】:

  • 你试过转义正则表达式中的大括号吗?
  • 这不是答案,而是评论

标签: sql regex joomla joomla-k2


【解决方案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][^\"]*",?)+\]}.*)' 我得到了正确的结果 谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-29
      • 2019-03-08
      • 1970-01-01
      • 2012-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      相关资源
      最近更新 更多