204 lines
8.8 KiB
SQL
204 lines
8.8 KiB
SQL
-- Statistics Overview Query
|
|
-- Provides statistics for BrickTracker dashboard
|
|
|
|
WITH
|
|
-- Set statistics aggregation
|
|
set_stats AS (
|
|
SELECT
|
|
COUNT(*) AS total_sets,
|
|
COUNT(DISTINCT "set") AS unique_sets,
|
|
COUNT(CASE WHEN "purchase_price" IS NOT NULL THEN 1 END) AS sets_with_price,
|
|
ROUND(SUM("purchase_price"), 2) AS total_cost,
|
|
ROUND(AVG("purchase_price"), 2) AS average_cost,
|
|
ROUND(MIN("purchase_price"), 2) AS minimum_cost,
|
|
ROUND(MAX("purchase_price"), 2) AS maximum_cost,
|
|
COUNT(DISTINCT CASE WHEN "storage" IS NOT NULL THEN "storage" END) AS storage_locations_used,
|
|
COUNT(DISTINCT CASE WHEN "purchase_location" IS NOT NULL THEN "purchase_location" END) AS purchase_locations_used,
|
|
COUNT(CASE WHEN "storage" IS NOT NULL THEN 1 END) AS sets_with_storage,
|
|
COUNT(CASE WHEN "purchase_location" IS NOT NULL THEN 1 END) AS sets_with_purchase_location
|
|
FROM "bricktracker_sets"
|
|
),
|
|
|
|
-- Part statistics aggregation (set-based parts)
|
|
set_part_stats AS (
|
|
SELECT
|
|
COUNT(*) AS total_part_instances,
|
|
COALESCE(SUM("quantity"), 0) AS total_parts_count,
|
|
COUNT(DISTINCT "part") AS unique_parts,
|
|
COALESCE(SUM("missing"), 0) AS total_missing_parts,
|
|
COALESCE(SUM("damaged"), 0) AS total_damaged_parts
|
|
FROM "bricktracker_parts"
|
|
),
|
|
|
|
-- Individual part statistics aggregation
|
|
individual_part_stats AS (
|
|
SELECT
|
|
COUNT(*) AS total_individual_parts,
|
|
COALESCE(SUM("quantity"), 0) AS total_individual_parts_count,
|
|
COUNT(DISTINCT "part") AS unique_individual_parts,
|
|
COALESCE(SUM("missing"), 0) AS total_missing_individual_parts,
|
|
COALESCE(SUM("damaged"), 0) AS total_damaged_individual_parts,
|
|
COUNT(CASE WHEN "purchase_price" IS NOT NULL AND "lot_id" IS NULL THEN 1 END) AS individual_parts_with_price,
|
|
COALESCE(ROUND(SUM(CASE WHEN "lot_id" IS NULL THEN "purchase_price" END), 2), 0) AS individual_parts_total_cost
|
|
FROM "bricktracker_individual_parts"
|
|
),
|
|
|
|
-- Combined part statistics
|
|
part_stats AS (
|
|
SELECT
|
|
set_part_stats.total_part_instances + COALESCE(individual_part_stats.total_individual_parts, 0) AS total_part_instances,
|
|
set_part_stats.total_parts_count + COALESCE(individual_part_stats.total_individual_parts_count, 0) AS total_parts_count,
|
|
(SELECT COUNT(DISTINCT "part") FROM (
|
|
SELECT "part" FROM "bricktracker_parts"
|
|
UNION
|
|
SELECT "part" FROM "bricktracker_individual_parts"
|
|
)) AS unique_parts,
|
|
set_part_stats.total_missing_parts + COALESCE(individual_part_stats.total_missing_individual_parts, 0) AS total_missing_parts,
|
|
set_part_stats.total_damaged_parts + COALESCE(individual_part_stats.total_damaged_individual_parts, 0) AS total_damaged_parts
|
|
FROM set_part_stats, individual_part_stats
|
|
),
|
|
|
|
-- Minifigure statistics aggregation (set-based minifigures)
|
|
set_minifig_stats AS (
|
|
SELECT
|
|
COUNT(*) AS total_minifigure_instances,
|
|
COALESCE(SUM("quantity"), 0) AS total_minifigures_count,
|
|
COUNT(DISTINCT "figure") AS unique_minifigures
|
|
FROM "bricktracker_minifigures"
|
|
),
|
|
|
|
-- Individual minifigure statistics aggregation
|
|
individual_minifig_stats AS (
|
|
SELECT
|
|
COUNT(*) AS total_individual_minifigures,
|
|
COALESCE(SUM("quantity"), 0) AS total_individual_minifigures_count,
|
|
COUNT(DISTINCT "figure") AS unique_individual_minifigures,
|
|
COUNT(CASE WHEN "purchase_price" IS NOT NULL THEN 1 END) AS individual_minifigs_with_price,
|
|
COALESCE(ROUND(SUM("purchase_price"), 2), 0) AS individual_minifigs_total_cost
|
|
FROM "bricktracker_individual_minifigures"
|
|
),
|
|
|
|
-- Combined minifigure statistics
|
|
minifig_stats AS (
|
|
SELECT
|
|
set_minifig_stats.total_minifigure_instances + COALESCE(individual_minifig_stats.total_individual_minifigures, 0) AS total_minifigure_instances,
|
|
set_minifig_stats.total_minifigures_count + COALESCE(individual_minifig_stats.total_individual_minifigures_count, 0) AS total_minifigures_count,
|
|
(SELECT COUNT(DISTINCT "figure") FROM (
|
|
SELECT "figure" FROM "bricktracker_minifigures"
|
|
UNION
|
|
SELECT "figure" FROM "bricktracker_individual_minifigures"
|
|
)) AS unique_minifigures
|
|
FROM set_minifig_stats, individual_minifig_stats
|
|
),
|
|
|
|
-- Part lot statistics aggregation
|
|
part_lot_stats AS (
|
|
SELECT
|
|
COUNT(*) AS total_part_lots,
|
|
COUNT(CASE WHEN "purchase_price" IS NOT NULL THEN 1 END) AS part_lots_with_price,
|
|
ROUND(SUM("purchase_price"), 2) AS part_lots_total_cost
|
|
FROM "bricktracker_individual_part_lots"
|
|
),
|
|
|
|
-- Combined min/max price across all item types (separate CTE to avoid scalar subquery issues in SQLite)
|
|
all_prices AS (
|
|
SELECT "purchase_price" AS price FROM "bricktracker_sets" WHERE "purchase_price" IS NOT NULL AND "purchase_price" != ''
|
|
UNION ALL
|
|
SELECT "purchase_price" FROM "bricktracker_individual_parts" WHERE "purchase_price" IS NOT NULL AND "purchase_price" != '' AND "lot_id" IS NULL
|
|
UNION ALL
|
|
SELECT "purchase_price" FROM "bricktracker_individual_minifigures" WHERE "purchase_price" IS NOT NULL AND "purchase_price" != ''
|
|
UNION ALL
|
|
SELECT "purchase_price" FROM "bricktracker_individual_part_lots" WHERE "purchase_price" IS NOT NULL AND "purchase_price" != ''
|
|
),
|
|
price_range AS (
|
|
SELECT
|
|
MIN(price) AS combined_minimum_cost,
|
|
MAX(price) AS combined_maximum_cost
|
|
FROM all_prices
|
|
),
|
|
|
|
-- Rebrickable sets count (for sets we actually own)
|
|
rebrickable_stats AS (
|
|
SELECT COUNT(*) AS unique_rebrickable_sets
|
|
FROM "rebrickable_sets"
|
|
WHERE "set" IN (SELECT DISTINCT "set" FROM "bricktracker_sets")
|
|
),
|
|
|
|
-- Combined financial statistics
|
|
financial_stats AS (
|
|
SELECT
|
|
-- Items with price
|
|
set_stats.sets_with_price +
|
|
COALESCE(individual_part_stats.individual_parts_with_price, 0) +
|
|
COALESCE(individual_minifig_stats.individual_minifigs_with_price, 0) +
|
|
COALESCE(part_lot_stats.part_lots_with_price, 0) AS total_items_with_price,
|
|
|
|
-- Total cost across all item types
|
|
ROUND(COALESCE(set_stats.total_cost, 0) +
|
|
COALESCE(individual_part_stats.individual_parts_total_cost, 0) +
|
|
COALESCE(individual_minifig_stats.individual_minifigs_total_cost, 0) +
|
|
COALESCE(part_lot_stats.part_lots_total_cost, 0), 2) AS combined_total_cost,
|
|
|
|
-- Average cost across all items with price
|
|
CASE
|
|
WHEN (set_stats.sets_with_price +
|
|
COALESCE(individual_part_stats.individual_parts_with_price, 0) +
|
|
COALESCE(individual_minifig_stats.individual_minifigs_with_price, 0) +
|
|
COALESCE(part_lot_stats.part_lots_with_price, 0)) > 0
|
|
THEN ROUND((COALESCE(set_stats.total_cost, 0) +
|
|
COALESCE(individual_part_stats.individual_parts_total_cost, 0) +
|
|
COALESCE(individual_minifig_stats.individual_minifigs_total_cost, 0) +
|
|
COALESCE(part_lot_stats.part_lots_total_cost, 0)) /
|
|
(set_stats.sets_with_price +
|
|
COALESCE(individual_part_stats.individual_parts_with_price, 0) +
|
|
COALESCE(individual_minifig_stats.individual_minifigs_with_price, 0) +
|
|
COALESCE(part_lot_stats.part_lots_with_price, 0)), 2)
|
|
ELSE 0
|
|
END AS combined_average_cost,
|
|
|
|
-- Min/Max price across all item types
|
|
price_range.combined_minimum_cost,
|
|
price_range.combined_maximum_cost
|
|
FROM set_stats, individual_part_stats, individual_minifig_stats, part_lot_stats, price_range
|
|
)
|
|
|
|
-- Final select combining all statistics
|
|
SELECT
|
|
-- Basic counts
|
|
set_stats.total_sets,
|
|
set_stats.unique_sets,
|
|
rebrickable_stats.unique_rebrickable_sets,
|
|
|
|
-- Parts statistics
|
|
part_stats.total_part_instances,
|
|
part_stats.total_parts_count,
|
|
part_stats.unique_parts,
|
|
part_stats.total_missing_parts,
|
|
part_stats.total_damaged_parts,
|
|
|
|
-- Minifigures statistics
|
|
minifig_stats.total_minifigure_instances,
|
|
minifig_stats.total_minifigures_count,
|
|
minifig_stats.unique_minifigures,
|
|
|
|
-- Financial statistics (set-only for backwards compatibility)
|
|
set_stats.sets_with_price,
|
|
set_stats.total_cost,
|
|
set_stats.average_cost,
|
|
set_stats.minimum_cost,
|
|
set_stats.maximum_cost,
|
|
|
|
-- Combined financial statistics (all item types)
|
|
financial_stats.total_items_with_price,
|
|
financial_stats.combined_total_cost,
|
|
financial_stats.combined_average_cost,
|
|
financial_stats.combined_minimum_cost,
|
|
financial_stats.combined_maximum_cost,
|
|
|
|
-- Storage and location statistics
|
|
set_stats.storage_locations_used,
|
|
set_stats.purchase_locations_used,
|
|
set_stats.sets_with_storage,
|
|
set_stats.sets_with_purchase_location
|
|
|
|
FROM set_stats, part_stats, minifig_stats, rebrickable_stats, financial_stats |