OUTER APPLY - SQL Server to MySQL Migration

SQL Server OUTER APPLY clause allows you to perform a correlated outer join (lateral join) often using a table-valued function or subquery. Correlated means that the right operand of a join clause contains a reference to the left operand.

In MySQL you can use LEFT OUTER JOIN LATERAL ON TRUE clause.

Consider a sample data:

  CREATE TABLE colors (name VARCHAR(30), arr VARCHAR(30));
  CREATE TABLE chars (c CHAR(1));
 
  INSERT INTO colors VALUES ('Green', '["g","r","e","e","n"]');
  INSERT INTO colors VALUES ('Red', '["r","e","d"]');
  INSERT INTO colors VALUES ('Black', NULL);
 
  INSERT INTO chars VALUES ('r');
  INSERT INTO chars VALUES ('e');
  INSERT INTO chars VALUES ('n');

SQL Server:

  -- Duplicate each 'colors' line for every row returned by table-valued function
  SELECT name, value
  FROM colors 
    OUTER APPLY OPENJSON(colors.arr) WITH (value CHAR '$') t;

Result:

name value
Green g
Green r
Green e
Green e
Green n
Red r
Red e
Red d
Black NULL

Note that 'Black' row is also returned by the query although the table-valued function returns NULL for it i.e outer join is performed.

In MySQL you can use LEFT OUTER JOIN LATERAL ON TRUE. Note that LATERAL keyword is not allowed for joins with table-valued functions:

MySQL:

  -- Duplicate each 'colors' line for every row returned by table-valued function
  SELECT name, value
  FROM colors 
     LEFT OUTER JOIN JSON_TABLE(colors.arr, '$[*]' COLUMNS (value CHAR(1) PATH '$')) t ON TRUE;

Result:

name value
Green g
Green r
Green e
Green e
Green n
Red r
Red e
Red d
Black NULL

Now let's perform OUTER APPLY using a subquery:

SQL Server:

  SELECT name, c
  FROM colors 
    OUTER APPLY (SELECT c FROM chars WHERE CHARINDEX(chars.c, colors.name) <> 0) c;

Result:

name c
Green r
Green e
Green n
Red r
Red e
Black NULL

In MySQL we now have to use LATERAL keyword for the correlated subquery:

MySQL:

  -- Join fails without LATERAL keyword
  SELECT name, c
  FROM colors 
    LEFT OUTER JOIN (SELECT c FROM chars WHERE INSTR(colors.name, chars.c) <> 0) c ON TRUE;
  -- ERROR 1054 (42S22): Unknown column 'colors.name' in 'where clause'
 
  -- Now with LATERAL
  SELECT name, c
  FROM colors 
    LEFT OUTER JOIN LATERAL (SELECT c FROM chars WHERE INSTR(colors.name, chars.c) <> 0) c ON TRUE;

Result:

name c
Green r
Green e
Green n
Red r
Red e
Black NULL

For more information, see SQL Server to MySQL Migration.