【问题标题】:Convert comma separated string to a list将逗号分隔的字符串转换为列表
【发布时间】:2018-09-06 16:19:10
【问题描述】:

我想传递一个 int 列表(逗号分隔),它是我表中的一个字段

即。 1234、2345、3456、4567

我在WHERE 中的IN 子句。但该列表是一个字符串 (VARCHAR),我正在与一个 int 字段进行比较。有没有办法将列表转换为整数列表?

Enterprise_ID 是 INT
路径是表中的一个字段,它是一个逗号分隔的字符串

即。 1234、2345、3456、4567

SELECT *
FROM tbl_Enterprise
WHERE Enterprise_ID IN ( Path )

我的数据库是 Vertica。

【问题讨论】:

  • 您可以控制数据库结构吗?列中以逗号分隔的整数列表强烈暗示您的数据库结构错误。
  • @MattGibson 我认为实际的问题是他作为参数传递给查询(逗号分隔数字的 varchar 列表),而不是 DB 结构。
  • @RaduGheorghiu 在列中存储多个值是结构问题。
  • @Kermit OP 没有提及将多个值存储在单个列中的任何内容(我同意,这是结构的问题)-"But the list is a string (VARCHAR), and I'm comparing to an int field"
  • @RaduGheorghiu 我明白你的解释。我认为你是对的!

标签: sql vertica


【解决方案1】:

您可以使用 vertica 中的 SPLIT_PART 函数将逗号分隔的列表拆分为行并将它们插入到临时表中。使用类似这样的查询来实现您的目标:

SELECT * FROM tbl_Enterprice WHERE Enterprice_ID IN ( Select Enterprice_ID from temp_table )

分割部分功能: https://my.vertica.com/docs/7.1.x/HTML/Content/Authoring/SQLReferenceManual/Functions/String/SPLIT_PART.htm

这是一个使用 split_part 将字符串拆分为行的示例:

dbadmin=> SELECT SPLIT_PART('JIM|TOM|PATRICK|PENG|MARK|BRIAN', '|', row_num) "User Names"
dbadmin->   FROM (SELECT ROW_NUMBER() OVER () AS row_num
dbadmin(>           FROM tables) row_nums
dbadmin->  WHERE SPLIT_PART('JIM|TOM|PATRICK|PENG|MARK|BRIAN', '|', row_num) <> '';
 User Names
------------
 JIM
 TOM
 PATRICK
 PENG
 MARK
 BRIAN
(6 rows)

【讨论】:

  • 感谢您的建议,但 Split_Part 用于获取字符串的特定部分。如何使用 split_part 获取行中以逗号分隔的所有 ID?
  • 我添加了一个使用 split_part 将字符串拆分为行的示例。请调整它以适合您的使用。希望这会有所帮助!
【解决方案2】:

我认为这两种解决方案是反模式,并建议对它们进行性能测试。

第一种方法使用 flex table 包中的函数。

SELECT values::INT as var1
FROM (
    SELECT MapItems(v1) OVER () AS (keys, values)
    FROM (
        SELECT MapDelimitedExtractor( '1234, 2345, 3456, 4567' 
                                       USING PARAMETERS DELIMITER=',') AS v1
    ) AS T
) AS T2
WHERE REGEXP_SUBSTR(values,'\d+',1) IS NOT NULL;
 var1 
------
 1234
 2345
 3456
 4567
(4 rows)

第二种方法使用文本索引包中的函数。

SELECT words::INT AS var1 
FROM (
    SELECT TxtIndex.StringTokenizerDelim('1234, 2345, 3456, 4567',',') 
           OVER() AS (words, input_string)
) AS T
WHERE REGEXP_SUBSTR(words, '\d+',1) IS NOT NULL;
 var1 
------
 1234
 2345
 3456
 4567
(4 rows)

【讨论】:

    【解决方案3】:

    Abnay 建议的稍微改进的解决方案版本:

    SELECT SPLIT_PART('JIM|TOM|PATRICK|PENG|MARK|BRIAN|AAA', '|', row_num) "User Names"
    FROM (SELECT ROW_NUMBER() OVER () AS row_num FROM columns) row_nums
    WHERE  REGEXP_COUNT('JIM|TOM|PATRICK|PENG|MARK|BRIAN|AAA', '\|') + 2 > row_num
    

    【讨论】:

      【解决方案4】:

      为什么不使用 find_in_set

      SELECT *
      

      来自 tbl_Enterprise WHERE FIND_IN_SET(企业 ID,路径)

      【讨论】:

        【解决方案5】:

        字符串连接是一项繁重的任务,所以我建议你避免它。由于您决定将它们保存为字符串而不是创建“父子”表,因此我建议您以这种方式保存它们 ,1234,2345,3456,4567,(在值的开头和结尾添加 ,并修剪所有空格)。

        然后你就可以用sql轻松搜索了,例如:

        SELECT * FROM tbl_Enterprice WHERE Enterprice_ID like ('%,your_value,%')
        

        【讨论】:

          猜你喜欢
          • 2013-02-04
          • 1970-01-01
          • 2012-09-04
          • 2023-04-02
          • 2014-08-24
          • 2020-04-04
          • 1970-01-01
          • 1970-01-01
          • 2012-01-17
          相关资源
          最近更新 更多