SQL中的分隔函数,用于在分号

时间:2017-08-24 05:24:13

标签: sql sql-server tsql split

我有以下数据。

Original Data

我只对程序B感兴趣。如何使用SQL语法将其更改为下表?

Program B Only

下面是我的语法,但它没有给我我想要的东西。

SELECT
  SUBSTRING(Program, 0, CHARINDEX(';', Program)),
  SUBSTRING(
      SUBSTRING(Program, CHARINDEX(';', Program) + 1, LEN(Program)),
      0,
      CHARINDEX(';', SUBSTRING(Program, CHARINDEX(';', Program) + 1,
                               LEN(Program)))),
  REVERSE(SUBSTRING(REVERSE(Program), 0, CHARINDEX(';', REVERSE(Program)))),
  File_Count
FROM DataBase1
WHERE Program LIKE '%B%'

谢谢你们的帮助。

博纳亚阿迪

2 个答案:

答案 0 :(得分:0)

试试这个:

SELECT
CASE WHEN PATINDEX('%B[0-9][0-9]%', Program)>0 THEN SUBSTRING(Program, PATINDEX('%B[0-9][0-9]%', Program) - 1, 4) 
     WHEN PATINDEX('%B[0-9]%', Program)>0 THEN SUBSTRING(Program, PATINDEX('%B[0-9]%', Program) - 1, 3) 
     ELSE '' END

FROM DataBase1 

第一个WHEN负责提取模式B[0-9][0-9],即当B后跟两个数字时,第二个用于提取B后跟一个数字。如果未找到匹配项,则默认返回空字符串。如果您有兴趣提取模式B后跟三位数,则需要在(作为第一种情况)时添加另一个,输入模式B[-9][0-9][0-9]而不是B[0-9][0-9]并将最后一个数字从4更改为5(长度提取的字符串。)

PATINDEX返回找到匹配项的位置。

答案 1 :(得分:0)

如果您使用PostgreSql,您可以尝试下一个解决方案。

首先使用数据创建临时表:

CREATE TABLE temp.test AS (
  SELECT 'A1, B1' AS program, 1 AS file_count
  UNION
  SELECT 'B2', 1
  UNION
  SELECT 'A2, B3', 1
  UNION
  SELECT 'B4', 1
  UNION
  SELECT 'A3, B5', 2
  UNION
  SELECT 'B6', 2
  UNION
  SELECT 'B7', 2
  UNION
  SELECT 'B8', 1
  UNION
  SELECT 'B9', 1
  UNION
  SELECT 'C1;D1;A4;B10', 1
  UNION
  SELECT 'C2;D2;B11', 1
  UNION
  SELECT 'C3,D3,A5,B12', 1
  UNION
  SELECT 'C4;B14;D4;B11,B13', 1
);

我建议在一个程序单元格中可以包含几个B值(最后选择)。

之后使用regexp_matches查找单元格中的所有B并为每个file_count值(第一个内部选择)选择,并在每个程序之后选择:

SELECT
  b_program,
  sum(file_count)
FROM (
       SELECT
         (SELECT regexp_matches(program, 'B\d+')) [1] AS b_program,
         file_count
       FROM temp.test
       WHERE upper(program) LIKE '%B%') bpt
GROUP BY b_program
ORDER BY b_program;
相关问题