1

我在尝试运行的 SQL 语句方面需要帮助,我已经做了很多阅读和测试,但我无法得到正确的结果,因此我在这里提出了请求。

我正在尝试从已从两个源连接数据的列中提取数据,我想在连接之前和之后分隔数据,连接是“ - ”(连字符两边都有空格),可以是字母数字' - '之前或之后的字符,这是我需要的数据。只是为了增加复杂性,一些行没有连接数据,即没有“ - ”,当满足这一点时,可以简单地提取整个列值并将其视为 BB 端(参见下面的第一个 BB 示例) .

因此,当我完成后,我想将 AA 侧(- 之前)和 BB 侧(- 之后)分开,以允许单 BB 情况。

查看数据可能会出现以下场景。

BB<br>
AA - BB<br>
AA-aa - BB<br>
AA - BB-bb-cc<br>
AA-aa - BB-bb-cc<br>

对于上述所有场景,我可以让代码正常工作,但并非始终如一——您能否建议正确的代码,或者即使有更好的解决方案不会影响 SQL 性能。

我一直在尝试 AA 方面的示例:-

作品:

select substr('AA - BB-bb', 0, instr('AA - BB-bb', ' - ', 1, 1)-1) AS A_NAME 
from DUAL;

失败(仅获得 AA,而不是 AA-aa):

select substr('AA-aa - BB-bb', 0,instr('AA-aa - BB-bb', ' - ', 1, 1)-1) AS A_NAME
from DUAL;

我一直在尝试 BB 方面的示例:-

失败:

select SUBSTR('AA-aa - WHENEHEH', INSTR('AA-aa - WHENEHEH',' - ', -1, 1)+1, 100)
 B_NAME from dual;

谢谢,马克。

4

4 回答 4

1

如果你的分隔符肯定是“hypen 两边的空格”

然后你可以使用 CHR() 函数。

从你的尝试

select substr('AA-aa - BB-bb', 0,instr('AA-aa - BB-bb', ' - ', 1, 1)-1) AS A_NAME
from DUAL;

使用这样的东西

select substr('AA-aa - BB-bb',0,instr('AA-aa - BB-bb',chr(32))-1) from dual; /* ASCII value for space is chr(32) /*

输出/输出

AA-aa

select substr('AA-aa - BB-bb',instr('AA-aa - BB-bb',chr(32))+2,10) from dual;

输出/输出

“-BB”

于 2014-02-10T10:29:48.653 回答
0

这是我认为对你有用的东西。(我希望我正确理解了您的要求)我尝试了您提到的所有示例的查询,并且效果很好。

SELECT REGEXP_SUBSTR ('AA-aa - BB-bb-cc',
                  '[^ - ]+')
      "Right Side",
   SUBSTR ('AA-aa - BB-bb-cc',
             INSTR ('AA-aa - BB-bb-cc',
                    ' - ')
           + 2)
      "Left Side"
  FROM DUAL;

这个适用于除 BB 之外的所有内容,作为一种解决方法,您可以检查分隔符是否存在,如果不存在,您可以将整个值用于右侧。

SELECT    SUBSTR ('AA aa - BB',0,
           INSTR ('AA aa - BB',
                ' - ')
          )
    "Right Side",
SUBSTR('AA aa - BB',INSTR('AA aa - BB',
                  ' - ')+2)
      "Left Side"
 FROM DUAL;      
于 2013-01-24T21:46:56.717 回答
0

假设,如您的场景列表中所示,可以依赖模式“-BB”,您可以使用它来查找拆分。

WITH
DATA AS (
  SELECT 'BB' text FROM dual
  UNION ALL SELECT 'AA - BB' FROM dual
  UNION ALL SELECT 'AA-aa - BB' FROM dual
  UNION ALL SELECT 'AA - BB-bb-cc' FROM dual
  UNION ALL SELECT 'AA-aa - BB-bb-cc' FROM dual
  ),
break AS (
  SELECT text, instr(text, '- BB') breakpos  FROM DATA
)
SELECT
  text,
  CASE WHEN breakpos = 0 THEN NULL ELSE substr( text, 1, breakpos-1 ) END aa_side,
  case when breakpos = 0 then text else substr( text, breakpos+2) end bb_side
FROM break
;
于 2013-01-24T19:07:08.363 回答
0

您在第二列而不是第一列中显示单个值的条件有点奇怪,但这应该可以满足您的所有其他要求:

with testdata as (
select 'BB'  as input_col, 1 as row_num from dual
union
select 'AA - BB', 2 from dual
union
select 'AA-aa - BB',3 from dual
)
select testdata.row_num,
case when (regexp_instr(testdata.input_col,'(\ -\ )') > 0) then
  regexp_replace(testdata.input_col, '(.*)(\ -\ )(.*)$', '\1')
else null
end output_col1,
regexp_replace(testdata.input_col, '(.*)(\ -\ )(.*)$', '\3') as output_col2
from testdata
order by testdata.row_num;

编辑:我修改了上面的内容以添加案例检查。我承认通过 regexp_replace 本身可能有一种更雄辩的方法来做到这一点,但这也有效。

于 2013-01-24T19:11:31.933 回答