【问题标题】:Vertica SQL Function used to split string into separate columnsVertica SQL 函数用于将字符串拆分为单独的列
【发布时间】:2016-08-31 19:07:13
【问题描述】:

SQL 中有没有一种方法可以根据字符串中的分隔符将字符串拆分为 n 列。我知道 SPLIT_PART 函数有三个参数,即字符串、分隔符和字符串中的第 n 个分隔符。示例:

select 
  split_part('2016-01-01 00:11:00|Sprout|0', '|', 1),  split_part('2016-01-01 00:11:00|Sprout|0', '|', 2), split_part('2016-01-01 00:11:00|Sprout|0', '|', 3);

有没有办法在没有第三个参数的情况下做到这一点,您只需提供字符串和定界符,无论定界符出现在字符串中的多少列,您最终都会得到?

一旦 Vertica 允许基于 Python 的 UDF,我知道使用 .split() 方法可以轻松解决此问题,但目前有解决方案吗?我知道这可能是一个很长的机会,但我主要是出于好奇,因为使用 split_part 非常适合我的目的。

这不可能是一个可以接受的答案

【问题讨论】:

    标签: sql split vertica


    【解决方案1】:

    好的。如果您很高兴获得字符串的第 n 个标记,请尝试:

        SQL>SELECT
        ...>  regexp_substr(
        ...>    '2016-01-01 00:11:00|Sprout|0' -- source string
        ...>  , '[|]?([^|]+)' -- pattern (an optional bar, followed by many non-bars, which we remember as the 1st group)
        ...>  , 1             -- starting from begin of string: position 1
        ...>  , 1             -- the N-th occurrence
        ...>  , ''            -- no regexp modifier
        ...>  , 1             -- we want the only remembered group - the 1st
        ...>  ) the_first
        ...>, regexp_substr(
        ...>    '2016-01-01 00:11:00|Sprout|0' -- source string
        ...>  , '[|]?([^|]+)' -- pattern (an optional bar, followed by many non-bars, which we remember as the 1st group)
        ...>  , 1             -- starting from begin of string: position 1
        ...>  , 2             -- the N-th occurrence
        ...>  , ''            -- no regexp modifier
        ...>  , 1             -- we want the only remembered group - the 1st
        ...>  ) the_second
        ...>, regexp_substr(
        ...>    '2016-01-01 00:11:00|Sprout|0' -- source string
        ...>  , '[|]?([^|]+)' -- pattern (an optional bar, followed by many non-bars, which we remember as the 1st group)
        ...>  , 1             -- starting from begin of string: position 1
        ...>  , 3             -- the N-th occurrence
        ...>  , ''            -- no regexp modifier
        ...>  , 1             -- we want the only remembered group - the 1st
        ...>  ) the_third
        ...>;
        the_first                   |the_second                  |the_third
        2016-01-01 00:11:00         |Sprout                      |0
    

    但是,如果您想旋转您的分隔字符串,以便每个标记形成一个新行 - 两种可能性:

        SQL>-- manual, using regexp_substr ...
        ...>with
        ...>the_array as (
        ...>          select  1 as idx
        ...>union all select  2
        ...>union all select  3
        ...>union all select  4
        ...>union all select  5
        ...>union all select  6
        ...>union all select  7
        ...>union all select  8
        ...>union all select  9
        ...>union all select 10 -- increase if you might get a bigger array than one of 10 elements
        ...>)
        ...> ,concepts as (
        ...>select '2016-01-01 00:11:00|Sprout|0' as concepts_list
        ...>)
        ...>select * from (
        ...>  select
        ...>   idx
        ...>  ,trim(
        ...>    regexp_substr(
        ...>     concepts_list -- source string
        ...>    ,'[|]?([^|]+)' -- pattern (an optional bar, followed by many non-bars, which we remember as the 1st group)
        ...>    ,1             -- starting from begin of string: position 1
        ...>    ,idx           -- the idx-th occurrence
        ...>    ,''            -- no regexp modifier
        ...>    ,1             -- we want the only remembered group - the 1st
        ...>    )
        ...>   ) as concept
        ...>  from concepts
        ...>  cross join the_array
        ...>) foo
        ...>where concept <> ''
        ...>;
        idx                 |concept
                           1|2016-01-01 00:11:00
                           3|0
                           2|Sprout
        select succeeded; 3 rows fetched
        SQL>-- using the strings_package on:
        ...>-- https://github.com/vertica/Vertica-Extension-Packages/blob/master/strings_package/src/StringTokenizerDelim.cpp
        ...>WITH csvtab(id,delimstring) AS (
        ...>          SELECT 1,'2016-01-01 00:11:00|Sprout|0'
        ...>UNION ALL SELECT 2,'2016-01-02 00:11:00|Trout|1'
        ...>UNION ALL SELECT 3,'2016-01-03 00:11:00|Salmon|2'
        ...>UNION ALL SELECT 4,'2016-01-04 00:11:00|Bass|3'
        ...>)
        ...>SELECT id, words
        ...>FROM (
        ...>  SELECT id, v_txtindex.StringTokenizerDelim(delimstring,'|') OVER (PARTITION by id) FROM csvtab
        ...>) a
        ...>ORDER BY 1;
        id                  |words
                           1|2016-01-01 00:11:00
                           1|Sprout
                           1|0
                           2|2016-01-02 00:11:00
                           2|Trout
                           2|1
                           3|2016-01-03 00:11:00
                           3|Salmon
                           3|2
                           4|2016-01-04 00:11:00
                           4|Bass
                           4|3
        select succeeded; 12 rows fetched
    

    【讨论】:

    • 我更想知道是否可以在选择语句中没有 3 个项目的情况下获得单独的列。如果你熟悉 Python,我想要 string.split('|') 的效果。如果这在 SQL 中是不可能的,那就太好了。您的第一个示例是我可能要使用 vertica 函数 SPLIT_PART(string, delimiter,occurrence) 的路线。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    • 2023-01-31
    相关资源
    最近更新 更多