使用generate_series查找字符串的出现次数

时间:2017-02-03 06:19:21

标签: sql postgresql

查询:

 select id , DATASTRING from mixdatatable 

输出:

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

现在我想找到所有出现的&#39; A&#39;在列datastring中。

我尝试了以下查询,它为硬编码字符串提供了正确的输出,但我如何使用下面的查询与表格#mix;混合数据&#39;。

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;

输出:

Position 
4
8
29
31

预期产出:

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

4 个答案:

答案 0 :(得分:2)

不需要generate_series。

  • 删除最后一个'A'及其后的所有内容
  • 使用'A'
  • 将字符串拆分为带有标准的表格
  • 计算令牌长度+'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       |
+----+----------+

答案 1 :(得分:0)

请使用以下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

答案 2 :(得分:0)

我认为有这么多解决方案的事实很好地说明了PostgreSQL的查询语言是多么强大。

这是我的解决方案:

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;

答案 3 :(得分:0)

这里是另一种解决方案,它将每个数据字符串转换为数组,并使用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;

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