Search code examples
oracle-databaseoracle19c

Oracle JSON_QUERY with path as query column value


I try to get part of JSON column in each result row this select

SELECT TRIM(a.symbol),
       TRIM(a.ex_name),
       to_char(a.date_rw, 'dd-MON-yyyy'),
       a.pwr,
       a.last,
       JSON_QUERY(b.mval, '$."-9"') as value
FROM   adviser_log a
       INNER JOIN profit_model_d b
       ON a.date_rw = b.date_rw
WHERE  a.date_rw = '08-OCT-2021'

select result:

VERY    NAS  08-OCT-2021    -9  8.9443 {"sl":-3.6,"tp":5,"avg":1.368,"max":5,"min":-3.6,"count":1}

As a json path I put "-9" literal but I wanna put as path a.pwr is it possible I tried put CONCAT('$.', a.pwr) without result Is it any way to create dynamical json path into JSON_QUERy

I want to match part json which key compared with a.pwr to each row in select

Thx


Solution

  • You can use a function to dynamically get the JSON value:

    WITH FUNCTION get_value(
      value IN CLOB,
      path  IN VARCHAR2
    ) RETURN VARCHAR2
    IS
    BEGIN
      RETURN JSON_OBJECT_T( value ).get_object( path ).to_string();
    END;
    SELECT TRIM(a.symbol) AS symbol,
           TRIM(a.ex_name) AS ex_name,
           to_char(a.date_rw, 'dd-MON-yyyy') AS date_rw,
           a.pwr,
           a.last,
           get_value(b.mval, a.pwr) AS value
    FROM   adviser_log a
           INNER JOIN profit_model_d b
           ON a.date_rw = b.date_rw
    WHERE  a.date_rw = DATE '2021-10-08'
    

    Which, for your sample data:

    CREATE TABLE adviser_log (symbol, ex_name, date_rw, pwr, last) AS
    SELECT 'VERY', 'NAS', DATE '2021-10-08', -9, 8.9443 FROM DUAL;
    
    CREATE TABLE profit_model_d (date_rw DATE, mval CLOB CHECK (mval IS JSON));
    
    INSERT INTO profit_model_d (
      date_rw,
      mval
    ) VALUES (
      DATE '2021-10-08',
      '{"-9":{"sl":-3.6,"tp":5,"avg":1.368,"max":5,"min":-3.6,"count":1}}'
    );
    

    Outputs:

    SYMBOL EX_NAME DATE_RW PWR LAST VALUE
    VERY NAS 08-OCT-2021 -9 8.9443 {"sl":-3.6,"tp":5,"avg":1.368,"max":5,"min":-3.6,"count":1}

    db<>fiddle here