. 5 min read
I asked Gemini for some examples of using JSON_TABLE in Postgres 17.
Hey Gemini, can you explain the usage of JSON_TABLE in Postgres 17 to me with a few simple examples? Consider that I have a wide table with a JSONB column. Make sure you cover a case with JOINs.
JSON_TABLE in Postgres 17: Unpacking JSONB Data
The JSON_TABLE function in Postgres 17 is a powerful tool for extracting data from JSON arrays and converting it into relational format. This allows you to easily query and join data stored within JSONB columns.
1. Basic Example:
Let’s imagine you have a table named products with a JSONB column called attributes:
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT,
attributes JSONB
);
INSERT INTO products (name, attributes) VALUES
('T-Shirt', '{"sizes": ["S", "M", "L"], "colors": ["red", "blue"]}'),
('Jeans', '{"sizes": ["XS", "M", "XL"], "colors": ["black", "blue"]}'),
('Hat', '{"sizes": ["One Size"], "colors": ["green", "yellow", "black"]}');
Now, you can use JSON_TABLE to extract the sizes for each product:
SELECT
p.name,
jt.size
FROM
products p,
JSON_TABLE(p.attributes, '$.sizes[*]' COLUMNS (
size TEXT PATH '$'
)) AS jt;
Explanation:
products table (p) and use JSON_TABLE on the attributes column.'$.sizes[*]' specifies the path within the JSON to extract data from. The [*] wildcard selects all array elements.COLUMNS defines the output columns, in this case a single column named size of type TEXT with data extracted from the path $ (representing the current array element).jt for easier access.This query will output a table with product names and their corresponding sizes:
| name | size |
|---|---|
| T-Shirt | S |
| T-Shirt | M |
| T-Shirt | L |
| Jeans | XS |
| Jeans | M |
| Jeans | XL |
| Hat | One Size |
2. Example with JOIN:
Let’s say you have another table called orders with a product_id column:
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
product_id INT REFERENCES products(id),
quantity INT
);
INSERT INTO orders (product_id, quantity) VALUES
(1, 2),
(2, 1),
(3, 3);
You can now use JSON_TABLE to join the orders table with the extracted sizes from the products table:
SELECT
o.id AS order_id,
p.name AS product_name,
jt.size AS product_size,
o.quantity
FROM
orders o
JOIN
products p ON o.product_id = p.id,
JSON_TABLE(p.attributes, '$.sizes[*]' COLUMNS (
size TEXT PATH '$'
)) AS jt;
Explanation:
orders and products tables on the product_id.JSON_TABLE within the FROM clause to extract the sizes for each product, similar to the previous example.JSON_TABLE is then implicitly joined with the other tables based on the shared product_id.This query will output a table with order details, including the size of each ordered product:
| order_id | product_name | product_size | quantity |
|---|---|---|---|
| 1 | T-Shirt | S | 2 |
| 1 | T-Shirt | M | 2 |
| 1 | T-Shirt | L | 2 |
| 2 | Jeans | XS | 1 |
| 2 | Jeans | M | 1 |
| 2 | Jeans | XL | 1 |
| 3 | Hat | One Size | 3 |
These examples showcase the basic usage of JSON_TABLE and how it can be used with joins to effectively query and analyze data stored within JSONB columns in Postgres 17. Remember to adjust the JSON path and output columns based on your specific data structure and desired results.
Give me more examples
Alright, here are some more advanced examples of using JSON_TABLE in Postgres 17 with different scenarios:
3. Filtering with WHERE clause:
Let’s say you want to find all products that come in the color blue. You can filter the results of JSON_TABLE using a WHERE clause:
SELECT
p.name,
jt.color
FROM
products p,
JSON_TABLE(p.attributes, '$.colors[*]' COLUMNS (
color TEXT PATH '$'
)) AS jt
WHERE
jt.color = 'blue';
This query will only return rows where the extracted color value is “blue”:
| name | color |
|---|---|
| T-Shirt | blue |
| Jeans | blue |
4. Extracting multiple values from nested objects:
Imagine your attributes JSONB column contains nested objects like this:
{ "sizes": ["S", "M"], "details": { "material": "cotton", "made_in": "China" } }
You can extract values from both the nested details object and the top-level array:
SELECT
p.name,
jt.size,
jt.material,
jt.made_in
FROM
products p,
JSON_TABLE(
p.attributes,
'$' COLUMNS (
size TEXT PATH '$.sizes[0]', -- Extract first size only
material TEXT PATH '$.details.material',
made_in TEXT PATH '$.details.made_in'
)
) AS jt;
This will output a table with product names, the first size in the array, material, and country of manufacture.
5. Using LATERAL join for complex relationships:
LATERAL joins can be used with JSON_TABLE for more complex scenarios. Let’s say you have a table promotions with a JSONB column rules containing product IDs and their discounts:
CREATE TABLE promotions (
id SERIAL PRIMARY KEY,
name TEXT,
rules JSONB
);
INSERT INTO promotions (name, rules) VALUES
('Summer Sale', '{"products": [{"id": 1, "discount": 0.2}, {"id": 3, "discount": 0.1}]}');
You can use a LATERAL join to find the discount for each product in the orders table:
SELECT
o.id AS order_id,
p.name AS product_name,
jt.discount
FROM
orders o
JOIN
products p ON o.product_id = p.id
LEFT JOIN LATERAL
JSON_TABLE(
(SELECT rules FROM promotions WHERE name = 'Summer Sale'),
'$.products[*]' COLUMNS (
product_id INT PATH '$.id',
discount DECIMAL PATH '$.discount'
)
) AS jt ON p.id = jt.product_id;
This query uses a subquery to find the relevant promotion, then uses LATERAL join with JSON_TABLE to extract discounts for matching product IDs from the rules JSONB column.
These examples demonstrate more advanced usage of JSON_TABLE for querying and joining data within JSONB columns in Postgres 17. You can combine these techniques with various clauses and functions to efficiently extract and analyze your JSON data.