简体   繁体   English

使用 generate_series 查找字符串的出现

[英]Find occurrence of string using generate_series

Query:询问:

 select id , DATASTRING from mixdatatable 

Output:输出:

id          DATASTRING
1           131A131A- - <> <<<><<>< afa A A ...
2           2323354A12<><>A .....HELLO <> A

Now I want to find all occurrences of 'A' in the column datastring.现在我想在列数据字符串中找到所有出现的 'A'。

I tried the below query, which gives output correct for hard coded string but how can I use below query with table 'mixdatatable'.我尝试了下面的查询,它为硬编码字符串提供了正确的输出,但是如何将下面的查询与表“mixdatatable”一起使用。

select * 
from (
  select case 
            when (string_to_array(trim(trailing '.' from regexp_replace('131A131A- - <> <<<><<>< afa A A ...','(.)','\\1.','g')),'.'))[i]='A' 
             then i 
          end as Position 
  from generate_series(1,length('131A131A- - <> <<<><<>< afa A A ...')) i
 ) foo 
 where count is not null;

Output:输出:

Position 
4
8
29
31

expected output:预期输出:

ID      Position  
1       4
1       8
1       29
1       31
2       8
2       15
--      --

No need for generate_series.不需要 generate_series。

  • Remove the last 'A' and everything after it删除最后一个“A”及其后的所有内容
  • Split the string to table with ordinality, by 'A'将字符串按顺序拆分为表,按 'A'
  • Compute the running total of the tokens lengths + 'A' length计算令牌长度 + 'A' 长度的运行总和

select  m.id

       ,sum (length (u.token) + length ('A')) over 
        (
            partition by m.id 
            order by     u.i 
            rows         unbounded preceding
        ) - length ('A') + 1                    as Position 

from    mixdatatable as m

        cross join lateral  

        regexp_split_to_table (substring (datastring,'(.*)A'),'A') 
            with ordinality u(token,i)

+----+----------+
| id | position |
+----+----------+
| 1  | 4        |
+----+----------+
| 1  | 8        |
+----+----------+
| 1  | 29       |
+----+----------+
| 1  | 31       |
+----+----------+
| 2  | 8        |
+----+----------+
| 2  | 15       |
+----+----------+
| 2  | 31       |
+----+----------+

Please use below approch:请使用以下方法:

select cast(RIGHT(de.SRNO,10) as bigint) + 1 as SRNO from  
(select RIGHT(SRNO,10) as SRNO ,SRNO as ACT  FROM  table1) de 

left outer join 

(select RIGHT(SRNO,10) as SRNO ,SRNO as ACT  FROM  table1) de1 
on cast(RIGHT(de.SRNO,10)  as bigint) + 1 = cast(RIGHT(de1.SRNO,10)   as bigint)
where  cast(RIGHT(de1.SRNO,10) as bigint) is null  
ORDER BY SRNO asc

I think the fact that there are so many solutions shows well how powerful PostgreSQL's query language is.我认为有这么多解决方案的事实很好地说明了 PostgreSQL 的查询语言是多么强大。

Here is my solution:这是我的解决方案:

SELECT m.id, p.pos
FROM mixdatatable m
   JOIN LATERAL (
                   SELECT row_number() OVER () AS n,
                   count(*) OVER () AS total,
                   sum(length(s)) OVER all_prev + count(s) OVER all_prev AS pos
                   FROM regexp_split_to_table(datastring, 'A') s
                   WINDOW all_prev AS (ROWS UNBOUNDED PRECEDING)
                ) p
      ON p.n < p.total;

Here is another solution which turns each datastring into an array and uses the with ordinality option to generate the index numbers:这是另一种将每个数据字符串转换为数组并使用with ordinality选项生成索引号的解决方案:

select m.id, t.pos
from mixdatatable m
  cross join lateral unnest(string_to_array(m.datastring,null)) with ordinality as t(ch, pos)
where ch = 'A'
order by m.id, t.pos;

Online example: https://rextester.com/TAM31056在线示例: https : //rextester.com/TAM31056

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM