Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql:将逗号分隔的整数值和间隔转换为序列号_Sql_Regex_Postgresql_Postgresql 9.3 - Fatal编程技术网

Postgresql:将逗号分隔的整数值和间隔转换为序列号

Postgresql:将逗号分隔的整数值和间隔转换为序列号,sql,regex,postgresql,postgresql-9.3,Sql,Regex,Postgresql,Postgresql 9.3,我有一个表,其中包含以下内容: Value是一种varchar类型,用于存储逗号和破折号之类的字符串,以便执行任何操作。但通常它只包含数字、逗号和破折号来指定间隔 id | value | ------------------ 1 | 1,2,5,8-10 | 2 | 1,2,3 | 3 | 1-3 | 4 | 1-3, 4-5 | 5 | 1-2,2-3 | 我想执行一个select查询,以规范化的代码可读格式检索在数据库级别(而不是代

我有一个表,其中包含以下内容:

Value是一种varchar类型,用于存储逗号和破折号之类的字符串,以便执行任何操作。但通常它只包含数字、逗号和破折号来指定间隔

id | value      | 
------------------
1  | 1,2,5,8-10 |
2  | 1,2,3      |
3  | 1-3        |
4  | 1-3, 4-5   |
5  | 1-2,2-3    |
我想执行一个select查询,以规范化的代码可读格式检索在数据库级别(而不是代码级别)用逗号分隔的值,这就是为什么我需要选择这样的表

id | value      | normalized
-------------------------------
1  | 1,2,5,8-10 |1,2,5,8,9,10
2  | 1,2,3      |1,2,3
3  | 1-3        |1,2,3
4  | 1-3, 4-5   |1,2,3,4,5
5  | 1-2,2-3    |1,2,3

id为5的记录的特殊情况,即使它指定了2次,也应该只检索2次。postgres中是否已经有这样的功能?如果没有,我如何在Postgres sql中解析字符串并对数字进行排序?

这似乎是首选PL或简单C扩展中的过程的一个很好的例子。pl/perl、pl/pythonu或pl/v8将是我的选择

也就是说,使用SQL很容易。拆分以查找子范围,可以是单个数字或范围。然后为每个范围生成其上的_系列

e、 g:

您可以将其包装为SQL函数,或者将其用作表查询的一部分

应用于表,您会得到如下结果:

CREATE TABLE example
    ("id" int, "value" varchar)
;

INSERT INTO example
    ("id", "value")
VALUES
    (1, '1,2,5,8-10'),
    (2, '1,2,3'),
    (3, '1-3'),
    (4, '1-3, 4-5'),
    (5, '1-2,2-3')
;
当应用于一个表时,它的内容如下:

SELECT
  example.id,
  array_agg(DISTINCT n) AS expanded_set
FROM
   example,
   regexp_split_to_table(example.value, ',') subrange,
   regexp_split_to_array(subrange, '-') subrange_parts,
   generate_series(subrange_parts[1]::integer, 
                  coalesce(subrange_parts[2], subrange_parts[1])::integer
   ) n
 GROUP BY
   example.id;
添加原始列的结果:

 id | original_format |  expanded_set  
----+-----------------+----------------
  1 | 1,2,5,8-10      | {1,2,5,8,9,10}
  2 | 1,2,3           | {1,2,3}
  3 | 1-3             | {1,2,3}
  4 | 1-3, 4-5        | {1,2,3,4,5}
  5 | 1-2,2-3         | {1,2,3}
(5 rows)
这不会特别快,但可能还可以。如果不是,用C写一些更快的东西作为扩展,或者plperl之类的东西

要了解发生了什么,请阅读PostgreSQL手册的以下部分:

分组和聚合 聚合函数,特别是数组_agg 作为聚合限定符进行区分 PostgreSQL数组,我在这里使用它作为中间状态和结果 生成_级数函数 regexp_split_to_表和regexp_split_to_数组函数 横向查询,此处隐式使用,因为一个函数使用联接列表中另一个函数的结果。
上述示例仅适用于PostgreSQL 9.2及更新版本。如果您使用的是较旧的版本,则必须使用嵌套子查询层来解决缺少横向查询的问题。

因此,您有一种自定义的方法来存储一组可能不相交的范围,并希望将其转换为一个简单的范围。是的,正是。。。因为当用户输入数据时,数据是作为一个简单的字符串接收的,并且希望以这种方式检索数据。但是您不必担心数据是如何输入的,表单中的代码会处理它。除了逗号和破折号,它永远不会包含字符串。。我们允许用户这样输入,因为这是最符合逻辑的可读输入方式。。对于一段时间间隔,我们假设330-540。。你不能期望用户输入330331332…等等..我是postgres和sql的新手。。帮个小忙?:+投票支持真正有用的解释和阅读建议。。这对像我这样的初学者来说真的很有帮助:
 id | original_format |  expanded_set  
----+-----------------+----------------
  1 | 1,2,5,8-10      | {1,2,5,8,9,10}
  2 | 1,2,3           | {1,2,3}
  3 | 1-3             | {1,2,3}
  4 | 1-3, 4-5        | {1,2,3,4,5}
  5 | 1-2,2-3         | {1,2,3}
(5 rows)