SQL Server CROSS APPLY clause allows you to perform a correlated inner 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 PostgreSQL you can use CROSS JOIN LATERAL clause.
Consider a sample data:
-- Sample tables CREATE TABLE colors (name VARCHAR(30), letters VARCHAR(30)); CREATE TABLE chars (c CHAR(1)); -- Sample rows 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 CROSS APPLY STRING_SPLIT(colors.letters, ',');
Result:
name | value |
green | g |
green | r |
green | e |
green | e |
green | n |
red | r |
red | e |
red | d |
Note that 'Black' row is not returned by the query as the table-valued function returns NULL for it.
In PostgreSQL you can use CROSS JOIN LATERAL.
PostgreSQL:
-- Duplicate each 'colors' line for every row returned by table-valued function SELECT name, value FROM colors CROSS JOIN LATERAL UNNEST(STRING_TO_ARRAY(colors.letters, ',')) t(value);
Result:
name | value |
green | g |
green | r |
green | e |
green | e |
green | n |
red | r |
red | e |
red | d |
Now let's perform CROSS APPLY using a subquery:
SQL Server:
SELECT name, c FROM colors CROSS 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 |
In PostgreSQL we have to use LATERAL keyword for the correlated subquery:
PostgreSQL:
-- Join fails without LATERAL keyword SELECT name, c FROM colors CROSS JOIN (SELECT c FROM chars WHERE POSITION(chars.c IN colors.name) <> 0) c; /* ERROR: invalid reference to FROM-clause entry for table "colors" */ /* DETAIL: There is an entry for table "colors", but it cannot be referenced from this part of the query. */ /* HINT: To reference that table, you must mark this subquery with LATERAL. */ -- Now with LATERAL SELECT name, c FROM colors CROSS JOIN LATERAL (SELECT c FROM chars WHERE POSITION(chars.c IN colors.name) <> 0) c;
Result:
name | c |
green | r |
green | e |
green | n |
red | r |
red | e |
For more information, see SQL Server to PostgreSQL Migration.