【问题标题】:Anyway way to change this Oracle SQL statment to use regs?无论如何更改此 Oracle SQL 语句以使用 regs 的方法?
【发布时间】:2015-01-22 16:25:06
【问题描述】:

我正在研究一些 Oracle SQL,但我是新手。我的表“web_access_log”中有数据,列名是“活动”。我需要获取保存在第 4 个和第 5 个“/”之间的 col 中的数据,或者如果我可以从右边开始让并从第 1 个到第 2 个“/”中获取数据,那将是正确的剩下!下面是一个有效的 SQL 语句,但从左到右。我真的需要从右到左,也许在 REGEX 中更容易?

Table: web_access_log
col name: activity
Sample value: Download file:/webdocs/data/groupXXX/case/03_28_54_9_0000011856.pdf

这就是我现在拥有的

SQL:
select  SUBSTR(activity, INSTR(activity, '/', 1, 4) + 1, INSTR(activity, '/', 1, 5) - INSTR(activity, '/', 1, 4) -1) AS FILENAME,
COUNT (SUBSTR(activity, INSTR(activity, '/', 1, 4) + 1, INSTR(activity, '/', 1, 5) - INSTR(activity, '/', 1, 4)-1)) AS DOWNLOADS
FROM sa.web_access_log where application_id = 5339 and to_char(time_stamp, 'mm/yyyy') = '04/2011'
GROUP BY SUBSTR(activity, INSTR(activity, '/', 1, 4) + 1, INSTR(activity, '/', 1, 5) - INSTR(activity, '/', 1, 4) -1)
ORDER BY DOWNLOADS DESC;

【问题讨论】:

  • 您的previous question 有正则表达式和普通方法的答案!
  • 这在您的代码中失败 to_char(time_stamp, 'mm/yyyy') = '04/2011'
  • 该代码在这里可以工作,但它是从左到右的。我需要从右到左

标签: sql regex oracle substring


【解决方案1】:

类似的方法,但从右到左(向后)获取“/”

INSTR(download,'/',-1,2) ==> 获取最后一次出现的 '/' == -1 在这里意味着相反

提取值的函数:

CREATE OR REPLACE FUNCTION EXTRACT_FOLDER (str VARCHAR2)
RETURN VARCHAR 
AS
ret_str  VARCHAR2(4000);
BEGIN
    BEGIN
      ret_str := TRIM(BOTH '/' FROM 
              substr(
                      str,
                      INSTR(str,'/',-1,2),
                      INSTR(str,'/',-1,1)-INSTR(str,'/',-1,2)
                     )
               );

    EXCEPTION WHEN OTHERS THEN
     ret_str := NULL;
    END;
    return ret_str;
END;
/

您的查询:

select COUNT(1)
FROM ACCESS_LOG
WHERE EXTRACT_FOLDER(download) = 'case';

这将列出值,它是计数。

select EXTRACT_FOLDER(download), COUNT(1)
FROM ACCESS_LOG
GROUP BY EXTRACT_FOLDER(download);

无功能:

select COUNT(1)
FROM ACCESS_LOG
WHERE TRIM(BOTH '/' FROM 
              substr(
                      download,
                      INSTR(download,'/',-1,2),
                      INSTR(download,'/',-1,1)-INSTR(download,'/',-1,2)
                     )
               ) = 'case';

正则表达式方法

SELECT COUNT(1)
FROM ACCESS_LOG
   WHERE REGEXP_REPLACE(download, '(.*/(.*)/.*$)','\2') = 'case';

这是如何工作的?

.* 表示某个字符.. 零个或多个出现
$ 表示行尾
/.*$ 表示字符串以 / 开头直到行尾../03_28_54_9_0000011856.pdf
@ 987654331@ 表示带有 2 个斜线到行尾的字符串。这是我们感兴趣的……但这给我们带来了整条线……

现在,诀窍是括号....
(.*/(.*)/.*$) 将变为 (/webdocs/data/groupXXX/(case)/03_28_54_9_0000011856.pdf)

注意大括号.. 正则表达式替换现在将\1 作为外括号内的一个,整行.. 并且 \2 将拥有case

由于我们只使用\2,整个表达式被替换为case

;

【讨论】:

  • 但这是使用硬编码的值。我需要它来自数据库并像上面的示例一样分组和计数
  • 我不知道为什么这对 SQL Fiddle 有效,但对 Oracle SQL Developer 无效
  • @JMS 你能试试我现在更新的那个吗?应该易于维护!
  • 我不能像我的示例一样在一次 SQL 中需要它
  • @JMS 还添加了正则表达式方法。
【解决方案2】:

我确信有更好的方法可以做到这一点,但这似乎可行:

select regexp_replace(activity, '^.*/(.*)/.*$', '\2') from (select 'Download file:/webdocs/data/groupXXX/case/03_28_54_9_0000011856.pdf' as activity from dual) ;

这会返回:

case

这是从右边数第一个和第二个“/”之间的文本。

由于 Oracle 正则表达式默认是贪婪的,所以第一个“.*”会尽可能多地占用字符串,同时尊重正则表达式的其余部分,其中包括显式斜杠。所以结果是“\2”是最后两个斜杠之间的文本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 2017-02-07
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多