簡體   English   中英

Postgresql:將逗號分隔的整數值和間隔轉換為序列數

[英]Postgresql : Converting comma separated integer values and intervals to sequenced numbers

我有一個包含以下內容的表:

Value 是一種varchar類型,用於存儲commadashes等字符串字符,因此任何事情都可以進行。 但通常它只包含numberscommadash來指定間隔。

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 中很容易。 拆分以查找子范圍,可以是單個數字或范圍。 然后為每個范圍 generate_series 在它上面。

例如:

SELECT n 
FROM
   regexp_split_to_table('1,2,5,8-10', ',') subrange,
   regexp_split_to_array(subrange, '-') subrange_parts,
   generate_series(subrange_parts[1]::integer, 
                  coalesce(subrange_parts[2], subrange_parts[1])::integer
   ) n;

您可以將其包裝為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;

結果(添加了原始 col):

 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 手冊部分:

  • GROUP BY和聚合
  • 聚合函數,尤其是array_agg
  • DISTINCT作為聚合限定符
  • PostgreSQL 數組,我在這里用作中間狀態和結果
  • generate_series函數
  • regexp_split_to_tableregexp_split_to_array函數
  • LATERAL查詢,這里隱式使用,因為一個函數使用連接列表中另一個函數的結果。

上面的示例僅適用於 PostgreSQL 9.2 及更高版本。 如果您有舊版本,則必須使用嵌套子查詢層來解決缺少LATERAL

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM