Skip to content

JSON Applications

Tables

products — Products (name, price, stock, brand)

categories — Categories (parent-child hierarchy)

Concepts

JSON_EXTRACT, JSON_EACH, JSON_GROUP_ARRAY, JSON_GROUP_OBJECT, json_set, json_remove, JSON Path Expression

1. JSON Basic Extraction — Laptop CPU List

Extract product names and CPU specifications from all active products in the Laptop category. Products with NULL CPU specifications are excluded.

Hint 1: - Extract JSON internal values ​​with json_extract(specs, '$.cpu') - Filter categories by JOIN with categories table

Answer
SELECT
    p.name        AS product_name,
    json_extract(p.specs, '$.cpu') AS cpu
FROM products AS p
INNER JOIN categories AS cat ON p.category_id = cat.id
WHERE cat.slug LIKE 'laptop%'
  AND p.is_active = 1
  AND p.specs IS NOT NULL
ORDER BY p.name;

Result (top 7 of 22 rows)

product_name cpu
ASUS ExpertBook B5 White Intel Core i5-13500H
ASUS ExpertBook B5 [Special Limited E... Intel Core i9-13900H
ASUS ExpertBook B5 [Special Limited E... Intel Core i9-13900H
ASUS ROG Strix Scar 16 AMD Ryzen 7 7735HS
HP EliteBook 840 G10 Black [Special L... AMD Ryzen 7 7735HS
HP EliteBook 840 G10 Silver Apple M3 Max
HP Envy x360 15 Silver AMD Ryzen 9 7945HX

2. JSON Multiple Field Extraction — Notebook Spec Sheet

Create a spec sheet by extracting the screen size, CPU, RAM (GB), storage capacity (GB), and battery (hours) of your laptop product at once. Sort by price descending.

Hint 1: - Call json_extract multiple times to extract each field into a separate column - $.screen_size, $.cpu, $.ram_gb, $.storage_gb, $.battery_hours

Answer
SELECT
    p.name                                     AS product_name,
    p.price,
    json_extract(p.specs, '$.screen_size')     AS screen_size,
    json_extract(p.specs, '$.cpu')             AS cpu,
    json_extract(p.specs, '$.ram_gb')          AS ram_gb,
    json_extract(p.specs, '$.storage_gb')      AS storage_gb,
    json_extract(p.specs, '$.battery_hours')   AS battery_hours
FROM products AS p
INNER JOIN categories AS cat ON p.category_id = cat.id
WHERE cat.slug LIKE 'laptop%'
  AND p.is_active = 1
  AND p.specs IS NOT NULL
ORDER BY p.price DESC
LIMIT 20;

Result (top 7 of 20 rows)

product_name price screen_size cpu ram_gb storage_gb battery_hours
MacBook Air 15 M3 Silver 5,481,100.00 16 inch Intel Core i9-13900H NULL NULL 9
Razer Blade 18 Black 4,353,100.00 14 inch Intel Core i7-13700H NULL NULL 14
Razer Blade 16 Silver 3,702,900.00 16 inch AMD Ryzen 9 7945HX NULL NULL 7
Razer Blade 18 Black 2,987,500.00 14 inch Apple M3 NULL NULL 6
Razer Blade 18 White 2,483,600.00 14 inch Intel Core i9-13900H NULL NULL 8
ASUS ROG Strix Scar 16 2,452,500.00 15.6 inch AMD Ryzen 7 7735HS NULL NULL 14
ASUS ExpertBook B5 [Special Limited E... 2,121,600.00 15.6 inch Intel Core i9-13900H NULL NULL 8

3. Identifying products with NULL specs

Check the distribution by category of products without specs information (NULL). The goal is to determine which categories are missing specification information.

Hint 1: - WHERE p.specs IS NULL condition - Aggregated by GROUP BY Category name

Answer
SELECT
    cat.name          AS category,
    COUNT(*)          AS no_specs_count
FROM products AS p
INNER JOIN categories AS cat ON p.category_id = cat.id
WHERE p.specs IS NULL
  AND p.is_active = 1
GROUP BY cat.name
ORDER BY no_specs_count DESC;

Result (top 7 of 22 rows)

category no_specs_count
Power Supply (PSU) 11
Intel Socket 10
Case 10
Speakers/Headsets 9
AMD Socket 9
Switch/Hub 8
Mechanical 8

4. List JSON keys — utilizing json_each

Pick a laptop product and list all the keys included in the specs JSON. json_each uses table-valued functions.

Hint 1: - json_each(specs) returns each key-value pair in a JSON object as a row - Return columns: key, value, type - Select one product with LIMIT 1 and send it to json_each

Answer
SELECT
    je.key,
    je.value,
    je.type
FROM products AS p,
     json_each(p.specs) AS je
INNER JOIN categories AS cat ON p.category_id = cat.id
WHERE cat.slug LIKE 'laptop%'
  AND p.specs IS NOT NULL
  AND p.id = (
      SELECT MIN(p2.id) FROM products AS p2
      INNER JOIN categories AS c2 ON p2.category_id = c2.id
      WHERE c2.slug LIKE 'laptop%' AND p2.specs IS NOT NULL
  );

Result (6 rows)

key value type
screen_size 14 inch text
cpu Apple M3 text
ram 8GB text
storage 256GB text
weight_kg 1.70 real
battery_hours 6 integer

5. JSON Condition Filtering — Finding High-Performance Laptops

Look for a laptop with at least 32GB of RAM and at least 1024GB of storage. Displays product name, price, RAM, and storage capacity.

Hint 1: - Use JSON value as condition in WHERE clause like json_extract(specs, '$.ram_gb') >= 32 - Values ​​extracted from JSON are automatically converted to the appropriate type.

Answer
SELECT
    p.name       AS product_name,
    p.price,
    json_extract(p.specs, '$.ram_gb')      AS ram_gb,
    json_extract(p.specs, '$.storage_gb')  AS storage_gb,
    json_extract(p.specs, '$.cpu')         AS cpu
FROM products AS p
INNER JOIN categories AS cat ON p.category_id = cat.id
WHERE cat.slug LIKE 'laptop%'
  AND p.is_active = 1
  AND p.specs IS NOT NULL
  AND json_extract(p.specs, '$.ram_gb') >= 32
  AND json_extract(p.specs, '$.storage_gb') >= 1024
ORDER BY p.price DESC;

6. JSON-based group aggregation — average price by CPU

Find the average price and number of products by CPU specification for laptops and desktops. Shows only CPUs with 3 or more products.

Hint 1: - Use json_extract(specs, '$.cpu') for GROUP BY - Exclude minority groups with HAVING COUNT(*) >= 3

Answer
SELECT
    json_extract(p.specs, '$.cpu')     AS cpu,
    COUNT(*)                           AS product_count,
    ROUND(AVG(p.price))                AS avg_price,
    MIN(p.price)                       AS min_price,
    MAX(p.price)                       AS max_price
FROM products AS p
INNER JOIN categories AS cat ON p.category_id = cat.id
WHERE (cat.slug LIKE 'laptop%' OR cat.slug LIKE 'desktop%')
  AND p.is_active = 1
  AND p.specs IS NOT NULL
GROUP BY json_extract(p.specs, '$.cpu')
HAVING COUNT(*) >= 3
ORDER BY avg_price DESC;

Result (5 rows)

cpu product_count avg_price min_price max_price
Intel Core i9-13900H 6 2,500,767.00 1,179,900.00 5,481,100.00
AMD Ryzen 9 7945HX 4 2,077,100.00 1,214,600.00 3,702,900.00
Apple M3 4 1,800,425.00 1,345,900.00 2,987,500.00
Intel Core i5-13600K 3 1,581,033.00 1,093,200.00 1,849,900.00
AMD Ryzen 5 7600X 4 1,532,125.00 739,900.00 3,671,500.00

7. JSON-based statistics — Analysis by monitor panel type

In the monitor category, tally the number of products, average price, and average refresh rate by panel type (IPS/VA/OLED). Also check the resolution distribution of each panel type.

Hint 1: - Use json_extract(specs, '$.panel'), json_extract(specs, '$.refresh_rate') - Resolution distribution is processed as a separate query or conditional aggregation (CASE WHEN)

Answer
SELECT
    json_extract(p.specs, '$.panel')          AS panel_type,
    COUNT(*)                                   AS product_count,
    ROUND(AVG(p.price))                        AS avg_price,
    ROUND(AVG(json_extract(p.specs, '$.refresh_rate'))) AS avg_refresh_rate,
    SUM(CASE WHEN json_extract(p.specs, '$.resolution') = 'FHD' THEN 1 ELSE 0 END) AS fhd_count,
    SUM(CASE WHEN json_extract(p.specs, '$.resolution') = 'QHD' THEN 1 ELSE 0 END) AS qhd_count,
    SUM(CASE WHEN json_extract(p.specs, '$.resolution') = '4K'  THEN 1 ELSE 0 END) AS uhd_4k_count
FROM products AS p
INNER JOIN categories AS cat ON p.category_id = cat.id
WHERE cat.slug LIKE 'monitor%'
  AND p.is_active = 1
  AND p.specs IS NOT NULL
GROUP BY json_extract(p.specs, '$.panel')
ORDER BY avg_price DESC;

Result (3 rows)

panel_type product_count avg_price avg_refresh_rate fhd_count qhd_count uhd_4k_count
VA 6 1,668,967.00 135.00 0 3 3
OLED 7 986,571.00 131.00 4 2 1
IPS 8 785,600.00 114.00 3 4 1

8. Modifying JSON value with json_set (within SELECT)

Use SQLite's json_set function to check the result of adding the "warranty_years": 3 field to the laptop product's specs. Preview the converted JSON from a SELECT, not an actual UPDATE.

Hint 1: - json_set(specs, '$.warranty_years', 3) adds a new key to an existing JSON - If the key already exists, the value is overwritten. - It is checked only in SELECT, so the actual data is not changed

Answer
SELECT
    p.name         AS product_name,
    p.specs        AS original_specs,
    json_set(p.specs, '$.warranty_years', 3) AS modified_specs
FROM products AS p
INNER JOIN categories AS cat ON p.category_id = cat.id
WHERE cat.slug LIKE 'laptop%'
  AND p.specs IS NOT NULL
LIMIT 3;

Result (3 rows)

product_name original_specs modified_specs
Razer Blade 18 Black {"screen_size": "14 inch", "cpu": "Ap... {"screen_size":"14 inch","cpu":"Apple...
Razer Blade 18 White {"screen_size": "14 inch", "cpu": "In... {"screen_size":"14 inch","cpu":"Intel...
HP Envy x360 15 Silver {"screen_size": "15.6 inch", "cpu": "... {"screen_size":"15.6 inch","cpu":"AMD...

9. Removing a JSON key with json_remove (within a SELECT)

Compare the original with the result of removing the tdp_watts key from the GPU product's specs. Use the json_remove function.

Hint 1: - json_remove(specs, '$.tdp_watts') returns JSON with the specified key removed - Display specs and json_remove(...) results side by side for comparison with the original

Answer
SELECT
    p.name        AS product_name,
    p.specs       AS original_specs,
    json_remove(p.specs, '$.tdp_watts') AS specs_without_tdp
FROM products AS p
INNER JOIN categories AS cat ON p.category_id = cat.id
WHERE cat.slug LIKE 'gpu%'
  AND p.specs IS NOT NULL
LIMIT 5;

Result (5 rows)

product_name original_specs specs_without_tdp
MSI GeForce RTX 4070 Ti Super GAMING X {"vram": "12GB", "clock_mhz": 2447, "... {"vram":"12GB","clock_mhz":2447}
MSI Radeon RX 9070 VENTUS 3X White {"vram": "16GB", "clock_mhz": 1946, "... {"vram":"16GB","clock_mhz":1946}
ASUS TUF Gaming RTX 5080 White {"vram": "24GB", "clock_mhz": 2177, "... {"vram":"24GB","clock_mhz":2177}
MSI Radeon RX 7900 XTX GAMING X White {"vram": "12GB", "clock_mhz": 1587, "... {"vram":"12GB","clock_mhz":1587}
Gigabyte RTX 5090 AERO OC {"vram": "8GB", "clock_mhz": 2283, "t... {"vram":"8GB","clock_mhz":2283}

10. Comprehensive JSON analysis — Specification comparison report by category

Analyze product specs for all categories to find a list of unique keys included in JSON for each category and the occurrence rate of each key. This report allows you to see at a glance what specification information exists in which category.

Hint 1: - Spread all keys into rows with json_each(specs), then GROUP BY with category + key combination - Appearance rate = Number of products with that key / Total number of products in the category - Step by step aggregation using CTEs

Answer
WITH spec_keys AS (
    SELECT
        cat.name       AS category,
        je.key,
        COUNT(*)       AS key_count
    FROM products AS p
    INNER JOIN categories AS cat ON p.category_id = cat.id,
         json_each(p.specs) AS je
    WHERE p.specs IS NOT NULL
      AND p.is_active = 1
    GROUP BY cat.name, je.key
),
category_totals AS (
    SELECT
        cat.name       AS category,
        COUNT(*)       AS total_products
    FROM products AS p
    INNER JOIN categories AS cat ON p.category_id = cat.id
    WHERE p.specs IS NOT NULL
      AND p.is_active = 1
    GROUP BY cat.name
)
SELECT
    sk.category,
    sk.key               AS spec_key,
    sk.key_count,
    ct.total_products,
    ROUND(100.0 * sk.key_count / ct.total_products, 1) AS presence_pct
FROM spec_keys AS sk
INNER JOIN category_totals AS ct ON sk.category = ct.category
ORDER BY sk.category, sk.key_count DESC;

Result (top 7 of 68 rows)

category spec_key key_count total_products presence_pct
2-in-1 battery_hours 7 7 100.00
2-in-1 cpu 7 7 100.00
2-in-1 ram 7 7 100.00
2-in-1 screen_size 7 7 100.00
2-in-1 storage 7 7 100.00
2-in-1 weight_kg 7 7 100.00
AMD clock_mhz 6 8 75.00