如何处理此字符串?

Posted

技术标签:

【中文标题】如何处理此字符串?【英文标题】:How do I Process This String? 【发布时间】:2019-05-03 02:51:02 【问题描述】:

我的一张表中有一些结果,但结果各不相同;代表我需要拆分的一列中的多个条目。

这是我的 SQL 和结果:

    select REGEXP_COUNT(value,';') as cnt,
    description
    from mytable;
1   Managed By|xBossxBoss xBoss Number|X0910505569Time 
Requested|2009-04-15 20:47:11.0Time Arrived|2009-04-15 21:46:11.0;   
1   Managed By|Modern ManagementxBoss Number|Time Requested|2009-04- 
16 14:01:29.0Time Arrived|2009-04-16 14:44:11.0; 
2   Managed By|xBossxBoss Number|X091480092Time Requested|2009-05-28 
08:58:41.0Time Arrived|;Managed By|Jims AllocationxBoss xBoss 
Number|Time Requested|Time Arrived|;   

期望的输出:

R1:
Managed By: xBoss
Time Requested:2009-10-19 07:53:45.0
Time Arrived: 2009-10-19 07:54:46.0

R2:
Managed By:Own Arrangements
Number: x5876523
Time Requested: 2009-10-19 07:57:46.0
Time Arrived:

R3:
Managed By: xBoss
Time Requested:2009-10-19 08:07:27.0
    select   
    SPLIT_PART(description, '', 1), 
    SPLIT_PART(description, '', 2), 
    SPLIT_PART(description, '', 3), 
    SPLIT_PART(description, '', 4), 
    SPLIT_PART(description, '', 5) 
    as description_with_tag from mytable;

当计数为1 时这没问题,但是当描述中有多个; 时,它不会给我结果。

是否可以根据计数将其放入数组中?

【问题讨论】:

你想要达到什么输出?你想获得Managed By|xBoss,还是仅仅获得Managed By|xBoss?或者只是xBoss?随时编辑您的问题以提供更多详细信息。另外,你为什么在value 中计算分号却显示description John,我只想检索结果 xBoss,Managed By 的术语将始终相同,但 xBoss 会经常更改。分号决定了一个事件有多少事件。 select REGEXP_COUNT(value,';') 将告诉金额。 我还是一头雾水。您能否编辑您的问题以显示您希望每个输入行的输出?请提供多个示例。 这是原始形式的查询结果。 Managed By|xBossNumber|Time Requested|2009-10-19 07:53:45.0Time Arrived|2009-10-19 07:54:46.0;Managed By|Own ArrangementsNumber |x5876523Time Requested|2009-10-19 07:57:46.0Time Arrived|;Managed By|xBossNumber|Time Requested|2009-10-19 08:07:27.0到达时间|; 这就是我想为我的 ETL R1 操作结果的方式 管理人:xBoss 编号:请求时间:2009-10-19 07:53:45.0 到达时间:2009-10-19 07: 54:46.0; R2 管理人:自己的安排编号:x5876523 请求时间:2009-10-19 07:57:46.0 到达时间:; R3 管理人:xBoss 编号:请求时间:2009-10-19 08:07:27.0 到达时间:; 【参考方案1】:

首先,值得指出的是,这种格式的数据无法充分利用 Redshift 可以提供的所有优势。 Amazon Redshift 是一种列式数据库,当数据存储在适当的列中时,它可以提供惊人的性能。但是,从文本字段中选择特定文本总是会表现不佳。

因此,我的主要建议是将数据预处理为正常的行和列,以便 Redshift 可以为您提供最佳功能。

但是,为了回答您的问题,我建议您制作一个标量用户定义函数

CREATE FUNCTION f_extract_curly (s TEXT, key TEXT)
  RETURNS TEXT
STABLE
AS $$
  # List of items in brackets
  items = s[1:-1].split('')

  # Dictionary of Key|Value from items
  entries = i.split('|')[0]: i.split('|')[1] for i in items

  # Return desired value
  return entries.get(key, None)

$$ LANGUAGE plpythonu;

我加载了样本数据:

CREATE TABLE foo (
    description TEXT
);

INSERT INTO foo values('Managed By|xBossxBoss xBoss Number|X0910505569Time Requested|2009-04-15 20:47:11.0Time Arrived|2009-04-15 21:46:11.0;');
INSERT INTO foo values('Managed By|Modern ManagementxBoss Number|Time Requested|2009-04-16 14:01:29.0Time Arrived|2009-04-16 14:44:11.0;');
INSERT INTO foo values('Managed By|xBossxBoss Number|X091480092Time Requested|2009-05-28 08:58:41.0Time Arrived|;Managed By|Jims AllocationxBoss xBoss Number|Time Requested|Time Arrived|;');

然后我测试了它:

SELECT
  f_extract_curly(description, 'Managed By'),
  f_extract_curly(description, 'Time Requested')
FROM foo

得到了结果:

xBoss               2009-04-15 20:47:11.0
Modern Management   2009-04-16 14:01:29.0
xBoss   

它不知道如何处理指定了两次相同字段的行(中间有分号)。您没有提供足够的示例输入和输出行,让我无法确定在这种情况下您想要什么,但请随意调整代码以满足您的要求。

【讨论】:

这太棒了!有时我会收到超出范围的错误消息列表索引。请查看 svl_udf_log 了解更多信息如果找不到任何内容,我该如何返回空值? SELECT name, REGEXP_COUNT(sep_val,';'), f_extract_curly(SPLIT_PART(value,';',1),'Managed By'), f_extract_curly(SPLIT_PART(value,';',2 ),'请求的时间') FROM foo;这似乎有效,但我确实得到 [Amazon](500310) Invalid operation: IndexError: list index out of range. 我已经编辑了return 语句,所以如果没有这样的条目,它应该返回None。我不确定 Redshift 是否将 Python None 转换为 SQL NULL,所以请测试一下并告诉我们! 太棒了约翰...非常感谢您的帮助! :)【参考方案2】:

Redshift 中没有数组数据类型。有两种选择:

1) 首先split_part by ';',然后为第一个split_part 输出的每个索引分别合并结果,然后split_part 结果通过'',最后得到你需要的。

2) 创建 Python UDF 并使用 Python 处理这些字符串。我想这是您用例的最佳解决方案。

3) 在 Redshift 之外转换您的数据。从您的数据结构看来,在复制到 Redshift 之前处理它似乎要好得多,将数组取消嵌套成行并将对象中的键提取到列中。

【讨论】:

以上是关于如何处理此字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理此索引超出范围错误 (LINGO)

对 Haskell 的布局工具如何处理此代码感到困惑

在 VC++ 中获取读取访问冲突异常如何处理此异常?

如何处理此错误:__init__() 有一个意外的关键字参数“book_category”

如何处理 MaxUploadSizeExceededException

Freemarker 'Collection.contains' 功能