sql >> Database >  >> RDS >> Oracle

Hoe het aantal keren dat het scheidingsteken voorkomt in een tekenreeks te tellen, met uitzondering van die tussen aanhalingstekens

Verwijder eerst de gescheiden inhoud, tel daarna:

regexp_count (
    regexp_replace (
        regexp_replace (
            i.data_record
          , '(^|,)"[^"]*"(,|$)'
          , '\1\2'
        )
      , '(^|,)"[^"]*"(,|$)'
      , '\1\2'
    )
  , ',' 
) 

Het nesten van regexp_replace aanroepen zijn helaas nodig om opeenvolgende, door quotes gescheiden velden correct af te handelen:eventuele scheidingskomma's worden gebruikt door het regexp-patroon en worden dus niet in aanmerking genomen voor de volgende overeenkomst.

De regexen van Oracle ondersteunen de lookahead-operator niet, wat de natuurlijke manier zou zijn om met deze situatie om te gaan.

Gezien de prestatiehit van regexp_...-oproepen is het misschien beter om

. te gebruiken
length(i.data_record) - length ( replace ( regexp_replace ( i.data_record, '(^|,)"[^"]*"(,|$)', '\1\2' ),',','' ) )

Voorbehoud

Deze oplossing verwerkt geen dquotes binnen veldwaarden, die meestal worden weergegeven als "" of \" .

Het eerste geval kan elegant worden behandeld:in plaats van een "" . te interpreteren binnen een door aanhalingstekens gescheiden veld, beschouw de volledige veldinhoud als een nevenschikking van 1 of meer door aanhalingstekens gescheiden tekenreeksen die geen aanhalingstekens bevatten. Hoewel u deze route niet zou volgen bij het verwerken van de gegevens (alle dquotes zouden verloren gaan), kunt u dit perspectief gebruiken om te tellen:

regexp_count (
    regexp_replace (
        regexp_replace (
            i.data_record
          , '(^|,)("[^"]*")+(,|$)'  -- changed
          , '\1\3'                  -- changed
        )
      , '(^|,)("[^"]*")+(,|$)'   -- changed
      , '\1\3'                   -- changed
    )
  , ',' 
) 

Testgevallen

-- works
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;

select regexp_count ( regexp_replace ( regexp_replace ( '1,"""data"",and more so",2,"more data,and even more so"', '(^|,)("[^"]*")+(,|$)', '\1\3' ), '(^|,)("[^"]*")+(,|$)', '\1\3' ), ',' ) from dual;

-- fails
select regexp_count ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;
select regexp_count ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;


  1. sql om voor elke maand één record te selecteren met een som van de records van die maand

  2. Poortwaarde wijzigen configureApplicationServer-kenmerk Worklight

  3. Steekproef van Oracle, exact aantal resultaten nodig (voorbeeldclausule)

  4. PostgreSQL volgende waarde van de reeksen?