oracle-databasejson-table

how json_table is joined with another table in Oracle database?


In https://oracle-base.com/articles/19c/sql-nested-clause-instead-of-json_table-19c

the following query

SELECT j.id, jt.first_name, jt.last_name, jt.job, jt.email, jt.phone, jt.active
FROM   json_documents j,
       JSON_TABLE(j.data, '$'
         COLUMNS (first_name    VARCHAR2(50 CHAR)  PATH FirstName,
                  last_name     VARCHAR2(50 CHAR)  PATH LastName,
                  job           VARCHAR2(10 CHAR)  PATH Job,
                  email         VARCHAR2(100 CHAR) PATH ContactDetails.Email,
                  phone         VARCHAR2(50 CHAR)  PATH ContactDetails.Phone,
                  active        VARCHAR2(5 CHAR)   PATH Active)) jt;

means that two table json_documents and jt are inner joined. In this web-site, it mentioned that the above query is equvalent the following:

SELECT j.id, jt.first_name, jt.last_name, jt.job, jt.email, jt.phone, jt.active
FROM   json_documents j JOIN
       JSON_TABLE(j.data, '$'
         COLUMNS (first_name    VARCHAR2(50 CHAR)  PATH FirstName,
                  last_name     VARCHAR2(50 CHAR)  PATH LastName,
                  job           VARCHAR2(10 CHAR)  PATH Job,
                  email         VARCHAR2(100 CHAR) PATH ContactDetails.Email,
                  phone         VARCHAR2(50 CHAR)  PATH ContactDetails.Phone,
                  active        VARCHAR2(5 CHAR)   PATH Active)) jt ON 1=1;

But I can't understand how they are joined! Where is join column and what is the meaning of 1=1


Solution

  • A comma-join is the equivalent of a ANSI CROSS JOIN:

    SELECT j.id, jt.first_name
    FROM   json_documents j
           CROSS JOIN JSON_TABLE(
             j.data,
             '$'
             COLUMNS (
               first_name    VARCHAR2(50 CHAR)  PATH FirstName
             )
           ) jt;
    

    A CROSS JOIN is the same as an INNER JOIN with no filter on the join:

    SELECT j.id, jt.first_name
    FROM   json_documents j
           INNER JOIN JSON_TABLE(
             j.data,
             '$'
             COLUMNS (
               first_name    VARCHAR2(50 CHAR)  PATH FirstName
             )
           ) jt
           ON (1=1);
    

    There is no join column as the join is a CROSS JOIN and not an INNER JOIN. 1=1 is used to provide a condition for the join that is always true which effectively converts the JOIN back to a CROSS JOIN as every combination of rows will match the filter.


    Technically, there is a column that joins the JSON_TABLE to the driving table as the JSON_TABLE uses j.data - it isn't in the JOIN condition though, it is embedded in the JSON_TABLE.

    From Oracle 12 and later, you could equivalently use:

    SELECT j.id, jt.first_name
    FROM   json_documents j
           CROSS APPLY JSON_TABLE(
             j.data,
             '$'
             COLUMNS (
               first_name    VARCHAR2(50 CHAR)  PATH FirstName
             )
           );
    

    or:

    SELECT j.id, jt.first_name
    FROM   json_documents j
           CROSS JOIN LATERAL (
             SELECT *
             FROM   JSON_TABLE(
                      j.data,
                      '$'
                      COLUMNS (
                        first_name    VARCHAR2(50 CHAR)  PATH FirstName
                      )
                    )
           );
    

    The syntax of both these queries indicates that json_documents is the driving table and the JSON_TABLE is applied to each row of the driving table.