Aircraft registration - FAA database

14 September 2025 - Written by ML

Executive Summary

This analysis examines the US Federal Aviation Administration (FAA) aircraft registration database, providing insights into the current state of civil aviation in the United States. The database contains detailed information on over 300,000 registered aircraft, 35,000+ deregistered aircraft, and supporting reference data.

Key Findings

Database Overview

  • Total Registered Aircraft: 302,049
  • Total Deregistered Aircraft: 359,778
  • Aircraft Reference Records: 93,503
  • Engine Specifications: 4,708
  • Active Dealers: 11,743

Geographic Distribution

  • Top States: Texas (28,614), California (25,123), Florida (21,217)
  • International: 761 aircraft from Great Britain, 482 from other countries
  • Manufacturing: Boeing leads with 1,541 aircraft types, followed by Cessna (419)

Highlights

  • This report examines the US Federal Aviation Administration (FAA) database of aircraft registrations.

Aim

  • Explain what the database is, examine details within the database, discuss gaps in the database, and, provide sample select statements to extract summary information from the database.

Method

  • Set out steps to download the data files, reconstitute the database on local MySQL8 database, and interact with the database.

Background

  • who the FAA is

  • where the FAA sits within the US government

  • what aircraft registration data there is

  • how frequently the data is updated

  • steps to incorporate into MYSQL8

The FAA

The FAA is described by Wikipedia as a US Federal government agency within the US Department of Transport that regulates civil aviation in the United States. It is organized as:

Where the FAA sits

FAA
FAA
Source: Grok 2024-09-14 (query: show diagrammatically where the FAA sits within the US government band list for each level the person responsible for it and its superior departments)

U.S. Government
│
└── Executive Branch
    │ Responsible: President Donald Trump
    │ Superior: None (Head of the Executive Branch)
    │
    └── U.S. Department of Transportation (DOT)
        │ Responsible: Secretary Sean Duffy
        │ Superior: President / Executive Branch
        │
        ├── **Federal Aviation Administration (FAA)**
        │   │ Responsible: Administrator Bryan Bedford
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Federal Highway Administration (FHWA)
        │   │ Responsible: Administrator Shailen Bhatt
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Federal Motor Carrier Safety Administration (FMCSA)
        │   │ Responsible: Administrator Robin Lee
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Federal Railroad Administration (FRA)
        │   │ Responsible: Administrator Amit Bose
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Federal Transit Administration (FTA)
        │   │ Responsible: Administrator Veronica Vanterpool (acting)
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Maritime Administration (MARAD)
        │   │ Responsible: Administrator Ann Phillips
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── National Highway Traffic Safety Administration (NHTSA)
        │   │ Responsible: Administrator Sophie Shulman
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Pipeline and Hazardous Materials Safety Administration (PHMSA)
        │   │ Responsible: Administrator Tristan Brown
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Surface Transportation Board (STB)
        │   │ Responsible: Chair Martin J. Oberman
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Great Lakes St. Lawrence Seaway Development Corporation (GLS)
        │   │ Responsible: Administrator Vacant (acting: U.S. Army Corps of Engineers liaison)
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Office of the Secretary of Transportation (OST)
        │   │ Responsible: Secretary Sean Duffy
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Office of the Deputy Secretary
        │   │ Responsible: Deputy Secretary Vacant (acting: Under Secretary)
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Office of the General Counsel
        │   │ Responsible: General Counsel Sarah Levinson
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Office of Public Affairs
        │   │ Responsible: Assistant Secretary for Public Affairs Vacant (acting)
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Office of the Chief Information Officer (OCIO)
        │   │ Responsible: Chief Information Officer Vacant (acting)
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Office of Small and Disadvantaged Business Utilization (OSDBU)
        │   │ Responsible: Director April McDonald
        │   │ Superior: Secretary of Transportation / DOT
        │
        ├── Office of Civil Rights
        │   │ Responsible: Director Vacant (acting)
        │   │ Superior: Secretary of Transportation / DOT
        │
        └── Office of Inspector General (OIG)
            │ Responsible: Inspector General Eric Soskin
            │ Superior: Secretary of Transportation / DOT

And within the FAA the organization structure is:


Source: Grok 2024-09-14 (query: what is the organization structure for the FAA and Bryan Bedford)

U.S. Department of Transportation (DOT)
│ (Superior: Secretary Sean Duffy)
│
└── Federal Aviation Administration (FAA)
    │ Responsible: Administrator Bryan Bedford
    │ Role: Leads overall policy, safety, and operations; reports to DOT Secretary
    │
    ├── Deputy Administrator
    │   │ Responsible: Chris Rocheleau
    │   │ Role: Supports Administrator on daily management and initiatives
    │
    ├── Air Traffic Organization (ATO)
    │   │ Responsible: Chief Operating Officer (COO) Tim Arel (note: position noted as vacant in some reports due to recent staff changes)
    │   │ Role: Manages air navigation services, air traffic control, and the National Airspace System
    │   │
    │   ├── Air Traffic Service
    │   │   │ Responsible: Vice President (acting, post-2025 changes)
    │   │
    │   ├── Technical Operations
    │   │   │ Responsible: Vice President (vacant/acting)
    │   │
    │   └── Mission Support Services
    │       │ Responsible: Director (acting)
    │
    ├── Aviation Safety (AVS)
    │   │ Responsible: Associate Administrator David Boulter
    │   │ Role: Oversees certification of aircraft, pilots, and safety standards
    │   │
    │   ├── **Flight Standards Service (FS)**
    │   │   │ Responsible: Director (updated May 2025 chart)
    │   │
    │   ├── Aircraft Certification Service (AIR)
    │   │   │ Responsible: Director
    │   │
    │   └── Safety Assurance and Compliance
    │       │ Responsible: Director
    │
    ├── Airports (ARP)
    │   │ Responsible: Associate Administrator Chad Kanamori
    │   │ Role: Funds airport development and ensures airport safety/compliance
    │   │
    │   ├── Airport Planning and Programming
    │   │   │ Responsible: Director
    │   │
    │   └── Airport Safety and Standards
    │       │ Responsible: Director
    │
    ├── Commercial Space Transportation (AST)
    │   │ Responsible: Associate Administrator (vacant; previously Heidi Williams, impacted by 2025 staff reductions)
    │   │ Role: Regulates commercial space launches and re-entries
    │   │
    │   ├── Licensing and Evaluation
    │   │   │ Responsible: Director
    │   │
    │   └── Safety Assurance
    │       │ Responsible: Director
    │
    ├── Finance and Management (APM)
    │   │ Responsible: Associate Administrator (vacant due to 2025 DOGE-led eliminations)
    │   │ Role: Handles budget, HR, acquisitions, and facilities
    │   │
    │   ├── Financial Services
    │   │   │ Responsible: Director (acting)
    │   │
    │   └── Human Resources
    │       │ Responsible: Director
    │
    ├── Headquarters Offices (Policy and Support)
    │   │ Role: Provide cross-cutting functions like policy, legal, and communications; report to Administrator
    │   │
    │   ├── Office of Policy, International Affairs, and Environment (APL)
    │   │   │ Responsible: Assistant Administrator (updated July 2025 chart)
    │   │   │ Role: Develops policy and handles international aviation
    │   │
    │   ├── Office of the Chief Counsel (AGC)
    │   │   │ Responsible: Chief Counsel
    │   │   │ Role: Legal advice and enforcement
    │   │
    │   ├── Office of Communications
    │   │   │ Responsible: Director
    │   │   │ Role: Public affairs and media
    │   │
    │   ├── Office of Civil Rights
    │   │   │ Responsible: Director (assistant administrator position eliminated in 2025)
    │   │
    │   ├── Office of Audit and Evaluation
    │   │   │ Responsible: Director (position eliminated in 2025)
    │   │
    │   └── NextGen (Airspace Modernization)
    │       │ Responsible: Associate Administrator (acting)
    │       │ Role: Oversees tech upgrades for air traffic management

Responsibility for the upkeep of the aircraft registry:

Source: Grok (query: who is responsible for maintaining the FAA aircraft register? https://registry.faa.gov/aircraftinquiry)

- Responsibility is the FAA Aircraft Registration Branch (also known as the Aircraft Registry)

- Scope of role includes developing, maintaining, and operating the Federal registration and recordation system for U.S. civil aircraft. The branch also provides public access to these records via tools like the Aircraft Inquiry system at https://registry.faa.gov/aircraftinquiry.

For example: issue of aircraft registration certificates (approximately 126,000 annually), processing documents related to aircraft title and interests (about 184,000 per year), reserving and assigning N-Numbers (U.S. nationality marks), and managing the permanent records for over 290,000 active civil aircraft. 

- Organizational Placement: The Aircraft Registration Branch operates within the broader FAA structure under the Office of Aviation Safety (AVS). Specifically:

Parent Division: Registry Management Division (AFS-700), part of the **Flight Standards Service (AFS)**.

Location: Based at the Mike Monroney Aeronautical Center in Oklahoma City, Oklahoma, where physical records are maintained and public access is provided through the Public Documents Room.

Oversight: Reports up through the Associate Administrator for Aviation Safety (currently David Boulter) to FAA Administrator Bryan Bedford, and ultimately to the U.S. Department of Transportation (DOT) Secretary Sean Duffy.

Aircraft registration data

  • Aircraft registration data: FAA registry

  • Compressed download size: ≈ 60 MB

  • frequency of update: daily

  • details of the content of the compressed files can be found in the pdf document.

  • 8 files are included: document pdf (ardata.pdf); Aircraft Registration Master file (MASTER.txt); Aircraft Dealer Applicant file (DEALER.txt); Aircraft Document Index file (DOCINDEX.txt); Aircraft Reference file (ACFTREF.txt); Deregistered Aircraft file (DEREG.txt); Engine Reference file (ENGINE.txt); Reserve N-Number file (RESERVED.txt).

FAA Aircraft Registry – nightly files
File Last updated Size Type
DEREG.txt 12 Sep 2025 23:32 276.2 MB Plain Text
MASTER.txt 12 Sep 2025 23:24 188.1 MB Plain Text
RESERVED.txt 12 Sep 2025 23:25 25.1 MB Plain Text
DEALER.txt 12 Sep 2025 23:18 17.9 MB Plain Text
ACFTREF.txt 12 Sep 2025 22:51 14.7 MB Plain Text
DOCINDEX.txt 12 Sep 2025 23:20 1.6 MB Plain Text
ardata.pdf 8 May 2025 14:29 243 KB PDF Document
ENGINE.txt 12 Sep 2025 22:55 232 KB Plain Text

Database reconstitution

Database reconstitution took place in three steps:

  1. text file import into R and data tidy;

  2. import saved sql files into local version of Mysql;

  3. application of indexes to certain fields to smooth processing of database.

master

# FAA Aircraft Database Import and Data Cleaning Script
# This script imports the MASTER.txt file from the FAA Releasable Aircraft database
# and creates a clean dataframe with properly named columns

# Load required libraries
library(readr)
library(dplyr)
library(stringr)

# Set the file path
file_path <- "MASTER.txt"

# Read the data - it's a comma-separated file
# The file has a header row with column names
cat("Reading FAA Aircraft Database...\n")
aircraft_data <- read_csv(
  file_path,
  col_types = cols(.default = "c"),  # Read all columns as character initially
  na = c("", " ", "  ")  # Treat empty strings and spaces as NA
)

# Display basic information about the dataset
cat("Dataset dimensions:", dim(aircraft_data), "\n")
cat("Number of columns:", ncol(aircraft_data), "\n")
cat("Number of rows:", nrow(aircraft_data), "\n\n")

# Display original column names
cat("Original column names:\n")
print(colnames(aircraft_data))
cat("\n")

# Debug: Check for problematic column names
cat("Checking for problematic column names:\n")
cat("Number of columns:", ncol(aircraft_data), "\n")
cat("Any NA column names:", any(is.na(colnames(aircraft_data))), "\n")
cat("Any empty column names:", any(colnames(aircraft_data) == ""), "\n")
cat("Column names with issues:\n")
problematic_cols <- which(
  is.na(colnames(aircraft_data)) | colnames(aircraft_data) == ""
)
if (length(problematic_cols) > 0) {
  cat("Problematic column indices:", problematic_cols, "\n")
  cat("Problematic column names:", colnames(aircraft_data)[problematic_cols], "\n")
} else {
  cat("No problematic column names found.\n")
}
cat("\n")

# Clean up column names - make them MySQL-friendly
original_names <- names(aircraft_data)
new_names <- original_names %>%
  tolower() %>%                    # Convert to lowercase
  gsub("-", "_", .) %>%            # Replace hyphens with underscores
  gsub(" ", "_", .) %>%            # Replace spaces with underscores
  gsub("__+", "_", .) %>%          # Replace multiple underscores with single
  gsub("^_|_$", "", .) %>%         # Remove leading/trailing underscores
  gsub("^[0-9]", "col_\\1", .)     # Prefix numeric column names with 'col_'

# Apply the new names
names(aircraft_data) <- new_names

cat("Column names tidied for MySQL compatibility:\n")
for (i in seq_along(original_names)) {
  cat(sprintf("  %s -> %s\n", original_names[i], new_names[i]))
}

# Display first few rows to verify the import
cat("First 5 rows of the dataset:\n")
print(head(aircraft_data, 5))
cat("\n")

# Data cleaning (keep everything as character for SQL generation)
cat("Cleaning data...\n")

# Clean text fields - remove extra spaces
aircraft_data <- aircraft_data %>%
  mutate(
    # Clean text fields - remove extra spaces
    name = str_trim(name),
    city = str_trim(city),
    state = str_trim(state),
    zip_code = str_trim(zip_code),
    country = str_trim(country),
    
    # Clean n_number - remove extra spaces
    n_number = str_trim(n_number),
    
    # Clean serial_number - remove extra spaces
    serial_number = str_trim(serial_number)
  )


# Function to escape SQL strings and handle NULL values
escape_sql_string <- function(x) {
  if (is.na(x) || x == "" || x == " " || x == "NULL") {
    return("NULL")
  } else {
    # Escape single quotes and backslashes
    escaped <- gsub("'", "''", x)  # Escape single quotes
    escaped <- gsub("\\\\", "\\\\\\\\", escaped)  # Escape backslashes
    return(paste0("'", escaped, "'"))
  }
}

# Function to determine appropriate MySQL data types
get_mysql_type <- function(col_name, data) {
  # Check if column contains only numeric data
  numeric_data <- data[!is.na(data) & data != "" & data != " "]
  if (length(numeric_data) > 0) {
    is_numeric <- all(grepl("^[0-9.-]+$", numeric_data))
    if (is_numeric) {
      # Check if it's an integer or decimal
      has_decimal <- any(grepl("\\.", numeric_data))
      max_length <- max(nchar(numeric_data))
      
      if (has_decimal) {
        return(paste0("DECIMAL(", max_length + 2, ",2)"))
      } else {
        if (max_length <= 3) return("SMALLINT")
        if (max_length <= 5) return("INT")
        if (max_length <= 10) return("BIGINT")
        return(paste0("VARCHAR(", max_length, ")"))
      }
    }
  }
  
  # Check if it's a date column by name
  if (grepl("date", tolower(col_name))) {
    return("DATE")
  }
  
  # Default to VARCHAR with appropriate length
  max_length <- max(nchar(data[!is.na(data) & data != "" & data != " "]), default = 0)
  if (max_length == 0) max_length <- 1
  return(paste0("VARCHAR(", min(max_length * 2, 255), ")"))
}

# Generate CREATE TABLE statement
cat("\nGenerating SQL CREATE TABLE statement...\n")

# Generate column definitions
column_defs <- character()
for (col in names(aircraft_data)) {
  mysql_type <- get_mysql_type(col, aircraft_data[[col]])
  column_defs <- c(column_defs, paste0("  `", col, "` ", mysql_type))
}

create_table_sql <- paste0(
  "-- CREATE TABLE statement for aircraft master data\n",
  "-- Generated for MySQL 8.0\n\n",
  "DROP TABLE IF EXISTS `aircraft_master`;\n",
  "CREATE TABLE `aircraft_master` (\n",
  "  `id` INT AUTO_INCREMENT PRIMARY KEY,\n",
  paste(column_defs, collapse = ",\n"),
  "\n);\n\n"
)

# Generate INSERT statements
cat("Generating INSERT statements...\n")

# Process data in batches to avoid memory issues
batch_size <- 1000
total_rows <- nrow(aircraft_data)
num_batches <- ceiling(total_rows / batch_size)

# Prepare column names for INSERT
column_names <- paste0("`", names(aircraft_data), "`", collapse = ", ")
insert_header <- paste0("INSERT INTO `aircraft_master` (", column_names, ") VALUES\n")

# Start building the SQL file content
sql_content <- create_table_sql

cat("Processing", total_rows, "rows in", num_batches, "batches...\n")

for (batch_num in 1:num_batches) {
  start_row <- (batch_num - 1) * batch_size + 1
  end_row <- min(batch_num * batch_size, total_rows)
  
  cat("Processing batch", batch_num, "of", num_batches, "(rows", start_row, "-", end_row, ")\n")
  
  batch_data <- aircraft_data[start_row:end_row, ]
  
  # Generate VALUES for this batch
  values_list <- character()
  for (i in 1:nrow(batch_data)) {
    row_values <- sapply(batch_data[i, ], escape_sql_string)
    values_list <- c(values_list, paste0("(", paste(row_values, collapse = ", "), ")"))
  }
  
  # Add batch to SQL content
  batch_sql <- paste0(insert_header, paste(values_list, collapse = ",\n"), ";\n\n")
  sql_content <- paste0(sql_content, batch_sql)
}

# Write the complete SQL file
sql_output_file <- "aircraft_master_import.sql"
cat("Writing SQL file to:", sql_output_file, "\n")

writeLines(sql_content, sql_output_file)

# Also save as CSV for backup
csv_output_file <- paste0(
  "master_clean.csv"
)
cat("Saving CSV backup to:", csv_output_file, "\n")
write_csv(aircraft_data, csv_output_file)

# Generate summary statistics
cat("\nFiles generated successfully!\n")
cat("SQL file size:", file.info(sql_output_file)$size, "bytes\n")
cat("Total rows:", total_rows, "\n")
cat("Columns:", ncol(aircraft_data), "\n")

# Show column information
cat("\nColumn information:\n")
for (col in names(aircraft_data)) {
  mysql_type <- get_mysql_type(col, aircraft_data[[col]])
  non_null_count <- sum(!is.na(aircraft_data[[col]]) & aircraft_data[[col]] != "" & aircraft_data[[col]] != " ")
  cat(sprintf("  %-20s %-20s (%d non-null values)\n", col, mysql_type, non_null_count))
}

cat("\nTo import into MySQL 8, use:\n")
cat("mysql -u your_username -p your_database < ", sql_output_file, "\n")

cat("\nOr from within MySQL:\n")
cat("SOURCE ", sql_output_file, ";\n")

deregistered

# Script to open and load DEREG.txt into a dataframe
# File: 'DEREG.txt'
# This file contains information about deregistered aircraft

library(readr)
library(dplyr)
library(stringr)

# Set the file path
file_path <- "DEREG.txt"

# Check if file exists
if (!file.exists(file_path)) {
  stop("File not found: ", file_path)
}

cat("Loading DEREG.txt into dataframe...\n")
cat("File path:", file_path, "\n")

# Read the CSV file
# Using read_csv from readr for better performance and automatic type detection
dereg_df <- read_csv(file_path, 
                    col_types = cols(.default = "c"),  # Read all columns as character initially
                    show_col_types = FALSE)

# Display basic information about the dataframe
cat("\nDataframe loaded successfully!\n")
cat("Dimensions:", nrow(dereg_df), "rows x", ncol(dereg_df), "columns\n")
cat("Column names:\n")
for (i in seq_along(names(dereg_df))) {
  cat(sprintf("  %2d. %s\n", i, names(dereg_df)[i]))
}

# Display first few rows
cat("\nFirst 5 rows:\n")
print(head(dereg_df, 5))

# Display data types
cat("\nData types:\n")
str(dereg_df)

# Basic summary statistics
cat("\nBasic summary:\n")
cat("Total deregistered aircraft records:", nrow(dereg_df), "\n")


# Clean up column names - make them MySQL-friendly
original_names <- names(dereg_df)
new_names <- original_names %>%
  tolower() %>%                    # Convert to lowercase
  gsub("-", "_", .) %>%            # Replace hyphens with underscores
  gsub(" ", "_", .) %>%            # Replace spaces with underscores
  gsub("__+", "_", .) %>%          # Replace multiple underscores with single
  gsub("^_|_$", "", .) %>%         # Remove leading/trailing underscores
  gsub("^[0-9]", "col_\\1", .)     # Prefix numeric column names with 'col_'

# Apply the new names
names(dereg_df) <- new_names

cat("Column names tidied for MySQL compatibility:\n")
for (i in seq_along(original_names)) {
  cat(sprintf("  %s -> %s\n", original_names[i], new_names[i]))
}

# Function to escape SQL strings and handle NULL values
escape_sql_string <- function(x) {
  if (is.na(x) || x == "" || x == " " || x == "NULL") {
    return("NULL")
  } else {
    # Escape single quotes and backslashes
    escaped <- gsub("'", "''", x)  # Escape single quotes
    escaped <- gsub("\\\\", "\\\\\\\\", escaped)  # Escape backslashes
    return(paste0("'", escaped, "'"))
  }
}

# Function to determine appropriate MySQL data types
get_mysql_type <- function(col_name, data) {
  # Check if column contains only numeric data
  numeric_data <- data[!is.na(data) & data != "" & data != " "]
  if (length(numeric_data) > 0) {
    is_numeric <- all(grepl("^[0-9.-]+$", numeric_data))
    if (is_numeric) {
      # Check if it's an integer or decimal
      has_decimal <- any(grepl("\\.", numeric_data))
      max_length <- max(nchar(numeric_data))
      
      if (has_decimal) {
        return(paste0("DECIMAL(", max_length + 2, ",2)"))
      } else {
        if (max_length <= 3) return("SMALLINT")
        if (max_length <= 5) return("INT")
        if (max_length <= 10) return("BIGINT")
        return(paste0("VARCHAR(", max_length, ")"))
      }
    }
  }
  
  # Check if it's a date column
  if (grepl("date", tolower(col_name))) {
    return("DATE")
  }
  
  # Default to VARCHAR with appropriate length
  max_length <- max(nchar(data[!is.na(data) & data != "" & data != " "]), default = 0)
  if (max_length == 0) max_length <- 1
  return(paste0("VARCHAR(", min(max_length * 2, 255), ")"))
}

# Generate CREATE TABLE statement
cat("\nGenerating SQL CREATE TABLE statement...\n")

# Generate column definitions
column_defs <- character()
for (col in names(dereg_df)) {
  mysql_type <- get_mysql_type(col, dereg_df[[col]])
  column_defs <- c(column_defs, paste0("  `", col, "` ", mysql_type))
}

create_table_sql <- paste0(
  "-- CREATE TABLE statement for deregistered aircraft data\n",
  "-- Generated for MySQL 8.0\n\n",
  "DROP TABLE IF EXISTS `deregistered_aircraft`;\n",
  "CREATE TABLE `deregistered_aircraft` (\n",
  "  `id` INT AUTO_INCREMENT PRIMARY KEY,\n",
  paste(column_defs, collapse = ",\n"),
  "\n);\n\n"
)

# Generate INSERT statements
cat("Generating INSERT statements...\n")

# Process data in batches to avoid memory issues
batch_size <- 1000
total_rows <- nrow(dereg_df)
num_batches <- ceiling(total_rows / batch_size)

# Prepare column names for INSERT
column_names <- paste0("`", names(dereg_df), "`", collapse = ", ")
insert_header <- paste0("INSERT INTO `deregistered_aircraft` (", column_names, ") VALUES\n")

# Start building the SQL file content
sql_content <- create_table_sql

cat("Processing", total_rows, "rows in", num_batches, "batches...\n")

for (batch_num in 1:num_batches) {
  start_row <- (batch_num - 1) * batch_size + 1
  end_row <- min(batch_num * batch_size, total_rows)
  
  cat("Processing batch", batch_num, "of", num_batches, "(rows", start_row, "-", end_row, ")\n")
  
  batch_data <- dereg_df[start_row:end_row, ]
  
  # Generate VALUES for this batch
  values_list <- character()
  for (i in 1:nrow(batch_data)) {
    row_values <- sapply(batch_data[i, ], escape_sql_string)
    values_list <- c(values_list, paste0("(", paste(row_values, collapse = ", "), ")"))
  }
  
  # Add batch to SQL content
  batch_sql <- paste0(insert_header, paste(values_list, collapse = ",\n"), ";\n\n")
  sql_content <- paste0(sql_content, batch_sql)
}

# Write the complete SQL file
sql_output_file <- "deregistered_aircraft_import.sql"
cat("Writing SQL file to:", sql_output_file, "\n")

writeLines(sql_content, sql_output_file)

# Also save as CSV for backup
csv_output_file <- paste0(
  "dereg_clean.csv"
)
cat("Saving CSV backup to:", csv_output_file, "\n")
write_csv(dereg_df, csv_output_file)

# Generate summary statistics
cat("\nFiles generated successfully!\n")
cat("SQL file size:", file.info(sql_output_file)$size, "bytes\n")
cat("Total rows:", total_rows, "\n")
cat("Columns:", ncol(dereg_df), "\n")

# Show column information
cat("\nColumn information:\n")
for (col in names(dereg_df)) {
  mysql_type <- get_mysql_type(col, dereg_df[[col]])
  non_null_count <- sum(!is.na(dereg_df[[col]]) & dereg_df[[col]] != "" & dereg_df[[col]] != " ")
  cat(sprintf("  %-20s %-20s (%d non-null values)\n", col, mysql_type, non_null_count))
}

cat("\nTo import into MySQL 8, use:\n")
cat("mysql -u your_username -p your_database < ", sql_output_file, "\n")

cat("\nOr from within MySQL:\n")
cat("SOURCE ", sql_output_file, ";\n")

reserved

# Script to open and load RESERVED.txt into a dataframe
# File: 'RESERVED.txt'

library(readr)
library(dplyr)

# Set the file path
file_path <- "RESERVED.txt"

# Check if file exists
if (!file.exists(file_path)) {
  stop("File not found: ", file_path)
}

cat("Loading RESERVED.txt into dataframe...\n")
cat("File path:", file_path, "\n")

# Read the CSV file
# Using read_csv from readr for better performance and automatic type detection
reserved_df <- read_csv(file_path, 
                        col_types = cols(.default = "c"),  # Read all columns as character initially
                        show_col_types = FALSE)

# Display basic information about the dataframe
cat("\nDataframe loaded successfully!\n")
cat("Dimensions:", nrow(reserved_df), "rows x", ncol(reserved_df), "columns\n")
cat("Column names:\n")
for (i in seq_along(names(reserved_df))) {
  cat(sprintf("  %2d. %s\n", i, names(reserved_df)[i]))
}

# Display first few rows
cat("\nFirst 5 rows:\n")
print(head(reserved_df, 5))

# Display data types
cat("\nData types:\n")
str(reserved_df)

# Basic summary statistics
cat("\nBasic summary:\n")
cat("Total records:", nrow(reserved_df), "\n")
cat("Unique N-numbers:", length(unique(reserved_df$`N-NUMBER`)), "\n")
cat("Unique registrants:", length(unique(reserved_df$REGISTRANT)), "\n")

# 1. Tidy column names
cat("\nTidying column names...\n")

# Clean up column names - make them MySQL-friendly
original_names <- names(reserved_df)
new_names <- original_names %>%
  tolower() %>%                    # Convert to lowercase
  gsub("-", "_", .) %>%            # Replace hyphens with underscores
  gsub(" ", "_", .) %>%            # Replace spaces with underscores
  gsub("__+", "_", .) %>%          # Replace multiple underscores with single
  gsub("^_|_$", "", .) %>%         # Remove leading/trailing underscores
  gsub("^[0-9]", "col_\\1", .)     # Prefix numeric column names with 'col_'

# Apply the new names
names(reserved_df) <- new_names

cat("Column names tidied for MySQL compatibility:\n")
for (i in seq_along(original_names)) {
  cat(sprintf("  %s -> %s\n", original_names[i], new_names[i]))
}

# Function to escape SQL strings and handle NULL values
escape_sql_string <- function(x) {
  if (is.na(x) || x == "" || x == " " || x == "NULL") {
    return("NULL")
  } else {
    # Escape single quotes and backslashes
    escaped <- gsub("'", "''", x)  # Escape single quotes
    escaped <- gsub("\\\\", "\\\\\\\\", escaped)  # Escape backslashes
    return(paste0("'", escaped, "'"))
  }
}

# Function to determine appropriate MySQL data types
get_mysql_type <- function(col_name, data) {
  # Check if column contains only numeric data
  numeric_data <- data[!is.na(data) & data != "" & data != " "]
  if (length(numeric_data) > 0) {
    is_numeric <- all(grepl("^[0-9.-]+$", numeric_data))
    if (is_numeric) {
      # Check if it's an integer or decimal
      has_decimal <- any(grepl("\\.", numeric_data))
      max_length <- max(nchar(numeric_data))
      
      if (has_decimal) {
        return(paste0("DECIMAL(", max_length + 2, ",2)"))
      } else {
        if (max_length <= 3) return("SMALLINT")
        if (max_length <= 5) return("INT")
        if (max_length <= 10) return("BIGINT")
        return(paste0("VARCHAR(", max_length, ")"))
      }
    }
  }
  
  # Check if it's a date column
  if (grepl("date", tolower(col_name))) {
    return("DATE")
  }
  
  # Default to VARCHAR with appropriate length
  max_length <- max(nchar(data[!is.na(data) & data != "" & data != " "]), default = 0)
  if (max_length == 0) max_length <- 1
  return(paste0("VARCHAR(", min(max_length * 2, 255), ")"))
}

# Generate CREATE TABLE statement
cat("\nGenerating SQL CREATE TABLE statement...\n")

# Generate column definitions
column_defs <- character()
for (col in names(reserved_df)) {
  mysql_type <- get_mysql_type(col, reserved_df[[col]])
  column_defs <- c(column_defs, paste0("  `", col, "` ", mysql_type))
}

create_table_sql <- paste0(
  "-- CREATE TABLE statement for reserved numbers data\n",
  "-- Generated for MySQL 8.0\n\n",
  "DROP TABLE IF EXISTS `reserved_numbers`;\n",
  "CREATE TABLE `reserved_numbers` (\n",
  "  `id` INT AUTO_INCREMENT PRIMARY KEY,\n",
  paste(column_defs, collapse = ",\n"),
  "\n);\n\n"
)

# Generate INSERT statements
cat("Generating INSERT statements...\n")

# Process data in batches to avoid memory issues
batch_size <- 1000
total_rows <- nrow(reserved_df)
num_batches <- ceiling(total_rows / batch_size)

# Prepare column names for INSERT
column_names <- paste0("`", names(reserved_df), "`", collapse = ", ")
insert_header <- paste0("INSERT INTO `reserved_numbers` (", column_names, ") VALUES\n")

# Start building the SQL file content
sql_content <- create_table_sql

cat("Processing", total_rows, "rows in", num_batches, "batches...\n")

for (batch_num in 1:num_batches) {
  start_row <- (batch_num - 1) * batch_size + 1
  end_row <- min(batch_num * batch_size, total_rows)
  
  cat("Processing batch", batch_num, "of", num_batches, "(rows", start_row, "-", end_row, ")\n")
  
  batch_data <- reserved_df[start_row:end_row, ]
  
  # Generate VALUES for this batch
  values_list <- character()
  for (i in 1:nrow(batch_data)) {
    row_values <- sapply(batch_data[i, ], escape_sql_string)
    values_list <- c(values_list, paste0("(", paste(row_values, collapse = ", "), ")"))
  }
  
  # Add batch to SQL content
  batch_sql <- paste0(insert_header, paste(values_list, collapse = ",\n"), ";\n\n")
  sql_content <- paste0(sql_content, batch_sql)
}

# Write the complete SQL file
sql_output_file <- "reserved_numbers_import.sql"
cat("Writing SQL file to:", sql_output_file, "\n")

writeLines(sql_content, sql_output_file)

# Also save as CSV for backup
csv_output_file <- paste0(
  "reserved_clean.csv"
)
cat("Saving CSV backup to:", csv_output_file, "\n")
write_csv(reserved_df, csv_output_file)

# Generate summary statistics
cat("\nFiles generated successfully!\n")
cat("SQL file size:", file.info(sql_output_file)$size, "bytes\n")
cat("Total rows:", total_rows, "\n")
cat("Columns:", ncol(reserved_df), "\n")

# Show column information
cat("\nColumn information:\n")
for (col in names(reserved_df)) {
  mysql_type <- get_mysql_type(col, reserved_df[[col]])
  non_null_count <- sum(!is.na(reserved_df[[col]]) & reserved_df[[col]] != "" & reserved_df[[col]] != " ")
  cat(sprintf("  %-20s %-20s (%d non-null values)\n", col, mysql_type, non_null_count))
}

cat("\nTo import into MySQL 8, use:\n")
cat("mysql -u your_username -p your_database < ", sql_output_file, "\n")

cat("\nOr from within MySQL:\n")
cat("SOURCE ", sql_output_file, ";\n")


documentation

# Script to open and load DOCINDEX.txt into a dataframe
# File: 'DOCINDEX.txt'
# This file contains information about aircraft documentation and certification records

library(readr)
library(dplyr)
library(stringr)
library(tidyr)

# Set the file path
file_path <- "DOCINDEX.txt"

# Check if file exists
if (!file.exists(file_path)) {
  stop("File not found: ", file_path)
}

cat("Loading DOCINDEX.txt into dataframe...\n")
cat("File path:", file_path, "\n")

# Read the CSV file
# Using read_csv from readr for better performance and automatic type detection
docindex_df <- read_csv(file_path, 
                       col_types = cols(.default = "c"),  # Read all columns as character initially
                       show_col_types = FALSE)

# Display basic information about the dataframe
cat("\nDataframe loaded successfully!\n")
cat("Dimensions:", nrow(docindex_df), "rows x", ncol(docindex_df), "columns\n")
cat("Column names:\n")
for (i in seq_along(names(docindex_df))) {
  cat(sprintf("  %2d. %s\n", i, names(docindex_df)[i]))
}

# Display first few rows
cat("\nFirst 5 rows:\n")
print(head(docindex_df, 5))

# Display data types
cat("\nData types:\n")
str(docindex_df)


# Clean up column names - make them MySQL-friendly
original_names <- names(docindex_df)
new_names <- original_names %>%
  tolower() %>%                    # Convert to lowercase
  gsub("-", "_", .) %>%            # Replace hyphens with underscores
  gsub(" ", "_", .) %>%            # Replace spaces with underscores
  gsub("__+", "_", .) %>%          # Replace multiple underscores with single
  gsub("^_|_$", "", .) %>%         # Remove leading/trailing underscores
  gsub("^[0-9]", "col_\\1", .)     # Prefix numeric column names with 'col_'

# Apply the new names
names(docindex_df) <- new_names

cat("Column names tidied for MySQL compatibility:\n")
for (i in seq_along(original_names)) {
  cat(sprintf("  %s -> %s\n", original_names[i], new_names[i]))
}

# Function to escape SQL strings and handle NULL values
escape_sql_string <- function(x) {
  if (is.na(x) || x == "" || x == " " || x == "NULL") {
    return("NULL")
  } else {
    # Escape single quotes and backslashes
    escaped <- gsub("'", "''", x)  # Escape single quotes
    escaped <- gsub("\\\\", "\\\\\\\\", escaped)  # Escape backslashes
    return(paste0("'", escaped, "'"))
  }
}

# Function to determine appropriate MySQL data types
get_mysql_type <- function(col_name, data) {
  # Check if column contains only numeric data
  numeric_data <- data[!is.na(data) & data != "" & data != " "]
  if (length(numeric_data) > 0) {
    is_numeric <- all(grepl("^[0-9.-]+$", numeric_data))
    if (is_numeric) {
      # Check if it's an integer or decimal
      has_decimal <- any(grepl("\\.", numeric_data))
      max_length <- max(nchar(numeric_data))
      
      if (has_decimal) {
        return(paste0("DECIMAL(", max_length + 2, ",2)"))
      } else {
        if (max_length <= 3) return("SMALLINT")
        if (max_length <= 5) return("INT")
        if (max_length <= 10) return("BIGINT")
        return(paste0("VARCHAR(", max_length, ")"))
      }
    }
  }
  
  # Check if it's a date column
  if (grepl("date", tolower(col_name))) {
    return("DATE")
  }
  
  # Default to VARCHAR with appropriate length
  max_length <- max(nchar(data[!is.na(data) & data != "" & data != " "]), default = 0)
  if (max_length == 0) max_length <- 1
  return(paste0("VARCHAR(", min(max_length * 2, 255), ")"))
}

# Generate CREATE TABLE statement
cat("\nGenerating SQL CREATE TABLE statement...\n")

# Generate column definitions
column_defs <- character()
for (col in names(docindex_df)) {
  mysql_type <- get_mysql_type(col, docindex_df[[col]])
  column_defs <- c(column_defs, paste0("  `", col, "` ", mysql_type))
}

create_table_sql <- paste0(
  "-- CREATE TABLE statement for documentation index data\n",
  "-- Generated for MySQL 8.0\n\n",
  "DROP TABLE IF EXISTS `documentation_index`;\n",
  "CREATE TABLE `documentation_index` (\n",
  "  `id` INT AUTO_INCREMENT PRIMARY KEY,\n",
  paste(column_defs, collapse = ",\n"),
  "\n);\n\n"
)

# Generate INSERT statements
cat("Generating INSERT statements...\n")

# Process data in batches to avoid memory issues
batch_size <- 1000
total_rows <- nrow(docindex_df)
num_batches <- ceiling(total_rows / batch_size)

# Prepare column names for INSERT
column_names <- paste0("`", names(docindex_df), "`", collapse = ", ")
insert_header <- paste0("INSERT INTO `documentation_index` (", column_names, ") VALUES\n")

# Start building the SQL file content
sql_content <- create_table_sql

cat("Processing", total_rows, "rows in", num_batches, "batches...\n")

for (batch_num in 1:num_batches) {
  start_row <- (batch_num - 1) * batch_size + 1
  end_row <- min(batch_num * batch_size, total_rows)
  
  cat("Processing batch", batch_num, "of", num_batches, "(rows", start_row, "-", end_row, ")\n")
  
  batch_data <- docindex_df[start_row:end_row, ]
  
  # Generate VALUES for this batch
  values_list <- character()
  for (i in 1:nrow(batch_data)) {
    row_values <- sapply(batch_data[i, ], escape_sql_string)
    values_list <- c(values_list, paste0("(", paste(row_values, collapse = ", "), ")"))
  }
  
  # Add batch to SQL content
  batch_sql <- paste0(insert_header, paste(values_list, collapse = ",\n"), ";\n\n")
  sql_content <- paste0(sql_content, batch_sql)
}

# Write the complete SQL file
sql_output_file <- "documentation_index_import.sql"
cat("Writing SQL file to:", sql_output_file, "\n")

writeLines(sql_content, sql_output_file)

# Also save as CSV for backup
csv_output_file <- paste0(
  "docindex_clean.csv"
)
cat("Saving CSV backup to:", csv_output_file, "\n")
write_csv(docindex_df, csv_output_file)

# Generate summary statistics
cat("\nFiles generated successfully!\n")
cat("SQL file size:", file.info(sql_output_file)$size, "bytes\n")
cat("Total rows:", total_rows, "\n")
cat("Columns:", ncol(docindex_df), "\n")

# Show column information
cat("\nColumn information:\n")
for (col in names(docindex_df)) {
  mysql_type <- get_mysql_type(col, docindex_df[[col]])
  non_null_count <- sum(!is.na(docindex_df[[col]]) & docindex_df[[col]] != "" & docindex_df[[col]] != " ")
  cat(sprintf("  %-20s %-20s (%d non-null values)\n", col, mysql_type, non_null_count))
}

cat("\nTo import into MySQL 8, use:\n")
cat("mysql -u your_username -p your_database < ", sql_output_file, "\n")

cat("\nOr from within MySQL:\n")
cat("SOURCE ", sql_output_file, ";\n")


dealers

# Script to open and load DEALER.txt into a dataframe
# File: 'DEALER.txt'

library(readr)
library(dplyr)

# Set the file path
file_path <- "DEALER.txt"

# Check if file exists
if (!file.exists(file_path)) {
  stop("File not found: ", file_path)
}

cat("Loading DEALER.txt into dataframe...\n")
cat("File path:", file_path, "\n")

# Read the CSV file
# Using read_csv from readr for better performance and automatic type detection
dealer_df <- read_csv(file_path, 
                      col_types = cols(.default = "c"),  # Read all columns as character initially
                      show_col_types = FALSE)

# Display basic information about the dataframe
cat("\nDataframe loaded successfully!\n")
cat("Dimensions:", nrow(dealer_df), "rows x", ncol(dealer_df), "columns\n")
cat("Column names:\n")
for (i in seq_along(names(dealer_df))) {
  cat(sprintf("  %2d. %s\n", i, names(dealer_df)[i]))
}

# Display first few rows
cat("\nFirst 5 rows:\n")
print(head(dealer_df, 5))

# Display data types
cat("\nData types:\n")
str(dealer_df)

# 1. Tidy column names
cat("\nTidying column names...\n")

# Clean up column names - make them MySQL-friendly
original_names <- names(dealer_df)
new_names <- original_names %>%
  tolower() %>%                    # Convert to lowercase
  gsub("-", "_", .) %>%            # Replace hyphens with underscores
  gsub(" ", "_", .) %>%            # Replace spaces with underscores
  gsub("__+", "_", .) %>%          # Replace multiple underscores with single
  gsub("^_|_$", "", .) %>%         # Remove leading/trailing underscores
  gsub("^[0-9]", "col_\\1", .)     # Prefix numeric column names with 'col_'

# Apply the new names
names(dealer_df) <- new_names

cat("Column names tidied for MySQL compatibility:\n")
for (i in seq_along(original_names)) {
  cat(sprintf("  %s -> %s\n", original_names[i], new_names[i]))
}

# Function to escape SQL strings and handle NULL values
escape_sql_string <- function(x) {
  if (is.na(x) || x == "" || x == " " || x == "NULL") {
    return("NULL")
  } else {
    # Escape single quotes and backslashes
    escaped <- gsub("'", "''", x)  # Escape single quotes
    escaped <- gsub("\\\\", "\\\\\\\\", escaped)  # Escape backslashes
    return(paste0("'", escaped, "'"))
  }
}

# Function to determine appropriate MySQL data types
get_mysql_type <- function(col_name, data) {
  # Check if column contains only numeric data
  numeric_data <- data[!is.na(data) & data != "" & data != " "]
  if (length(numeric_data) > 0) {
    is_numeric <- all(grepl("^[0-9.-]+$", numeric_data))
    if (is_numeric) {
      # Check if it's an integer or decimal
      has_decimal <- any(grepl("\\.", numeric_data))
      max_length <- max(nchar(numeric_data))
      
      if (has_decimal) {
        return(paste0("DECIMAL(", max_length + 2, ",2)"))
      } else {
        if (max_length <= 3) return("SMALLINT")
        if (max_length <= 5) return("INT")
        if (max_length <= 10) return("BIGINT")
        return(paste0("VARCHAR(", max_length, ")"))
      }
    }
  }
  
  # Check if it's a date column
  if (grepl("date", tolower(col_name))) {
    return("DATE")
  }
  
  # Default to VARCHAR with appropriate length
  max_length <- max(nchar(data[!is.na(data) & data != "" & data != " "]), default = 0)
  if (max_length == 0) max_length <- 1
  return(paste0("VARCHAR(", min(max_length * 2, 255), ")"))
}

# Generate CREATE TABLE statement
cat("\nGenerating SQL CREATE TABLE statement...\n")

# Generate column definitions
column_defs <- character()
for (col in names(dealer_df)) {
  mysql_type <- get_mysql_type(col, dealer_df[[col]])
  column_defs <- c(column_defs, paste0("  `", col, "` ", mysql_type))
}

create_table_sql <- paste0(
  "-- CREATE TABLE statement for dealer data\n",
  "-- Generated for MySQL 8.0\n\n",
  "DROP TABLE IF EXISTS `dealers`;\n",
  "CREATE TABLE `dealers` (\n",
  "  `id` INT AUTO_INCREMENT PRIMARY KEY,\n",
  paste(column_defs, collapse = ",\n"),
  "\n);\n\n"
)

# Generate INSERT statements
cat("Generating INSERT statements...\n")

# Process data in batches to avoid memory issues
batch_size <- 1000
total_rows <- nrow(dealer_df)
num_batches <- ceiling(total_rows / batch_size)

# Prepare column names for INSERT
column_names <- paste0("`", names(dealer_df), "`", collapse = ", ")
insert_header <- paste0("INSERT INTO `dealers` (", column_names, ") VALUES\n")

# Start building the SQL file content
sql_content <- create_table_sql

cat("Processing", total_rows, "rows in", num_batches, "batches...\n")

for (batch_num in 1:num_batches) {
  start_row <- (batch_num - 1) * batch_size + 1
  end_row <- min(batch_num * batch_size, total_rows)
  
  cat("Processing batch", batch_num, "of", num_batches, "(rows", start_row, "-", end_row, ")\n")
  
  batch_data <- dealer_df[start_row:end_row, ]
  
  # Generate VALUES for this batch
  values_list <- character()
  for (i in 1:nrow(batch_data)) {
    row_values <- sapply(batch_data[i, ], escape_sql_string)
    values_list <- c(values_list, paste0("(", paste(row_values, collapse = ", "), ")"))
  }
  
  # Add batch to SQL content
  batch_sql <- paste0(insert_header, paste(values_list, collapse = ",\n"), ";\n\n")
  sql_content <- paste0(sql_content, batch_sql)
}

# Write the complete SQL file
sql_output_file <- "dealers_import.sql"
cat("Writing SQL file to:", sql_output_file, "\n")

writeLines(sql_content, sql_output_file)

# Also save as CSV for backup
csv_output_file <- paste0(
  "dealer_clean.csv"
)
cat("Saving CSV backup to:", csv_output_file, "\n")
write_csv(dealer_df, csv_output_file)

# Generate summary statistics
cat("\nFiles generated successfully!\n")
cat("SQL file size:", file.info(sql_output_file)$size, "bytes\n")
cat("Total rows:", total_rows, "\n")
cat("Columns:", ncol(dealer_df), "\n")

# Show column information
cat("\nColumn information:\n")
for (col in names(dealer_df)) {
  mysql_type <- get_mysql_type(col, dealer_df[[col]])
  non_null_count <- sum(!is.na(dealer_df[[col]]) & dealer_df[[col]] != "" & dealer_df[[col]] != " ")
  cat(sprintf("  %-20s %-20s (%d non-null values)\n", col, mysql_type, non_null_count))
}

cat("\nTo import into MySQL 8, use:\n")
cat("mysql -u your_username -p your_database < ", sql_output_file, "\n")

cat("\nOr from within MySQL:\n")
cat("SOURCE ", sql_output_file, ";\n")

aircraft reference

# Script to open and load ACFTREF.txt into a dataframe
# File: 'ACFTREF.txt'

library(readr)
library(dplyr)

# Set the file path
file_path <- "ACFTREF.txt"

# Check if file exists
if (!file.exists(file_path)) {
  stop("File not found: ", file_path)
}

cat("Loading ACFTREF.txt into dataframe...\n")
cat("File path:", file_path, "\n")

# Read the CSV file
# Using read_csv from readr for better performance and automatic type detection
acftref_df <- read_csv(file_path, 
                       col_types = cols(.default = "c"),  # Read all columns as character initially
                       show_col_types = FALSE)

# Display basic information about the dataframe
cat("\nDataframe loaded successfully!\n")
cat("Dimensions:", nrow(acftref_df), "rows x", ncol(acftref_df), "columns\n")
cat("Column names:\n")
for (i in seq_along(names(acftref_df))) {
  cat(sprintf("  %2d. %s\n", i, names(acftref_df)[i]))
}

# Display first few rows
cat("\nFirst 5 rows:\n")
print(head(acftref_df, 5))

# Display data types
cat("\nData types:\n")
str(acftref_df)

# 1. Tidy column names
cat("\nTidying column names...\n")

# Remove the extra empty column if it exists
if ("...14" %in% names(acftref_df)) {
  acftref_df <- acftref_df %>% select(-"...14")
  cat("Removed empty column '...14'\n")
}

# Clean up column names - make them MySQL-friendly
original_names <- names(acftref_df)
new_names <- original_names %>%
  tolower() %>%                    # Convert to lowercase
  gsub("-", "_", .) %>%            # Replace hyphens with underscores
  gsub(" ", "_", .) %>%            # Replace spaces with underscores
  gsub("__+", "_", .) %>%          # Replace multiple underscores with single
  gsub("^_|_$", "", .) %>%         # Remove leading/trailing underscores
  gsub("^[0-9]", "col_\\1", .)     # Prefix numeric column names with 'col_'

# Apply the new names
names(acftref_df) <- new_names

cat("Column names tidied for MySQL compatibility:\n")
for (i in seq_along(original_names)) {
  cat(sprintf("  %s -> %s\n", original_names[i], new_names[i]))
}

# Function to escape SQL strings and handle NULL values
escape_sql_string <- function(x) {
  if (is.na(x) || x == "" || x == " " || x == "NULL") {
    return("NULL")
  } else {
    # Escape single quotes and backslashes
    escaped <- gsub("'", "''", x)  # Escape single quotes
    escaped <- gsub("\\\\", "\\\\\\\\", escaped)  # Escape backslashes
    return(paste0("'", escaped, "'"))
  }
}

# Function to determine appropriate MySQL data types
get_mysql_type <- function(col_name, data) {
  # Check if column contains only numeric data
  numeric_data <- data[!is.na(data) & data != "" & data != " "]
  if (length(numeric_data) > 0) {
    is_numeric <- all(grepl("^[0-9.-]+$", numeric_data))
    if (is_numeric) {
      # Check if it's an integer or decimal
      has_decimal <- any(grepl("\\.", numeric_data))
      max_length <- max(nchar(numeric_data))
      
      if (has_decimal) {
        return(paste0("DECIMAL(", max_length + 2, ",2)"))
      } else {
        if (max_length <= 3) return("SMALLINT")
        if (max_length <= 5) return("INT")
        if (max_length <= 10) return("BIGINT")
        return(paste0("VARCHAR(", max_length, ")"))
      }
    }
  }
  
  # Check if it's a date column
  if (grepl("date", tolower(col_name))) {
    return("DATE")
  }
  
  # Default to VARCHAR with appropriate length
  max_length <- max(nchar(data[!is.na(data) & data != "" & data != " "]), default = 0)
  if (max_length == 0) max_length <- 1
  return(paste0("VARCHAR(", min(max_length * 2, 255), ")"))
}

# Generate CREATE TABLE statement
cat("\nGenerating SQL CREATE TABLE statement...\n")

# Generate column definitions
column_defs <- character()
for (col in names(acftref_df)) {
  mysql_type <- get_mysql_type(col, acftref_df[[col]])
  column_defs <- c(column_defs, paste0("  `", col, "` ", mysql_type))
}

create_table_sql <- paste0(
  "-- CREATE TABLE statement for aircraft reference data\n",
  "-- Generated for MySQL 8.0\n\n",
  "DROP TABLE IF EXISTS `aircraft_reference`;\n",
  "CREATE TABLE `aircraft_reference` (\n",
  "  `id` INT AUTO_INCREMENT PRIMARY KEY,\n",
  paste(column_defs, collapse = ",\n"),
  "\n);\n\n"
)

# Generate INSERT statements
cat("Generating INSERT statements...\n")

# Process data in batches to avoid memory issues
batch_size <- 1000
total_rows <- nrow(acftref_df)
num_batches <- ceiling(total_rows / batch_size)

# Prepare column names for INSERT
column_names <- paste0("`", names(acftref_df), "`", collapse = ", ")
insert_header <- paste0("INSERT INTO `aircraft_reference` (", column_names, ") VALUES\n")

# Start building the SQL file content
sql_content <- create_table_sql

cat("Processing", total_rows, "rows in", num_batches, "batches...\n")

for (batch_num in 1:num_batches) {
  start_row <- (batch_num - 1) * batch_size + 1
  end_row <- min(batch_num * batch_size, total_rows)
  
  cat("Processing batch", batch_num, "of", num_batches, "(rows", start_row, "-", end_row, ")\n")
  
  batch_data <- acftref_df[start_row:end_row, ]
  
  # Generate VALUES for this batch
  values_list <- character()
  for (i in 1:nrow(batch_data)) {
    row_values <- sapply(batch_data[i, ], escape_sql_string)
    values_list <- c(values_list, paste0("(", paste(row_values, collapse = ", "), ")"))
  }
  
  # Add batch to SQL content
  batch_sql <- paste0(insert_header, paste(values_list, collapse = ",\n"), ";\n\n")
  sql_content <- paste0(sql_content, batch_sql)
}

# Write the complete SQL file
sql_output_file <- "aircraft_reference_import.sql"
cat("Writing SQL file to:", sql_output_file, "\n")

writeLines(sql_content, sql_output_file)

# Also save as CSV for backup
csv_output_file <- paste0(
  "acftref_clean.csv"
)
cat("Saving CSV backup to:", csv_output_file, "\n")
write_csv(acftref_df, csv_output_file)

# Generate summary statistics
cat("\nFiles generated successfully!\n")
cat("SQL file size:", file.info(sql_output_file)$size, "bytes\n")
cat("Total rows:", total_rows, "\n")
cat("Columns:", ncol(acftref_df), "\n")

# Show column information
cat("\nColumn information:\n")
for (col in names(acftref_df)) {
  mysql_type <- get_mysql_type(col, acftref_df[[col]])
  non_null_count <- sum(!is.na(acftref_df[[col]]) & acftref_df[[col]] != "" & acftref_df[[col]] != " ")
  cat(sprintf("  %-20s %-20s (%d non-null values)\n", col, mysql_type, non_null_count))
}

cat("\nTo import into MySQL 8, use:\n")
cat("mysql -u your_username -p your_database < ", sql_output_file, "\n")

cat("\nOr from within MySQL:\n")
cat("SOURCE ", sql_output_file, ";\n")


engine

# Script to open and load ENGINE.txt into a dataframe
# File: 'ENGINE.txt'

library(readr)
library(dplyr)
library(stringr)
library(tidyr)

# Set the file path
file_path <- "engine.txt"

# Check if file exists
if (!file.exists(file_path)) {
  stop("File not found: ", file_path)
}

cat("Loading ENGINE.txt into dataframe...\n")
cat("File path:", file_path, "\n")

# Read the CSV file
# Using read_csv from readr for better performance and automatic type detection
engine_df <- read_csv(file_path, 
                     col_types = cols(.default = "c"),  # Read all columns as character initially
                     show_col_types = FALSE)

# Display basic information about the dataframe
cat("\nDataframe loaded successfully!\n")
cat("Dimensions:", nrow(engine_df), "rows x", ncol(engine_df), "columns\n")
cat("Column names:\n")
for (i in seq_along(names(engine_df))) {
  cat(sprintf("  %2d. %s\n", i, names(engine_df)[i]))
}

# Display first few rows
cat("\nFirst 5 rows:\n")
print(head(engine_df, 5))

# Display data types
cat("\nData types:\n")
str(engine_df)

# Basic summary statistics
cat("\nBasic summary:\n")
cat("Total records:", nrow(engine_df), "\n")

# Check for unique values in key columns
if ("MFR" %in% names(engine_df)) {
  cat("Unique manufacturers:", length(unique(engine_df$MFR)), "\n")
  cat("Sample manufacturers:\n")
  sample_mfrs <- unique(engine_df$MFR)[1:10]
  for (mfr in sample_mfrs) {
    cat("  -", mfr, "\n")
  }
}

if ("MODEL" %in% names(engine_df)) {
  cat("\nUnique models:", length(unique(engine_df$MODEL)), "\n")
  cat("Sample models:\n")
  sample_models <- unique(engine_df$MODEL)[1:10]
  for (model in sample_models) {
    cat("  -", model, "\n")
  }
}

# Check for engine type information
if ("TYPE" %in% names(engine_df)) {
  cat("\nEngine types:\n")
  engine_types <- table(engine_df$TYPE, useNA = "ifany")
  print(engine_types)
  
  # Add engine type descriptions (from FAA ardata.pdf)
  cat("\nEngine type descriptions:\n")
  type_descriptions <- c(
    "0" = "None",
    "1" = "Reciprocating",
    "2" = "Turbo-prop",
    "3" = "Turbo-shaft",
    "4" = "Turbo-jet",
    "5" = "Turbo-fan",
    "6" = "Ramjet",
    "7" = "2 Cycle",
    "8" = "4 Cycle",
    "9" = "Unknown",
    "10" = "Electric",
    "11" = "Rotary"
  )
  
  for (type_code in names(engine_types)) {
    if (type_code %in% names(type_descriptions)) {
      cat("  Type", type_code, ":", type_descriptions[type_code], "(", engine_types[type_code], "engines)\n")
    } else {
      cat("  Type", type_code, ": Unknown (", engine_types[type_code], "engines)\n")
    }
  }
}

# Check for horsepower information
if ("HORSEPOWER" %in% names(engine_df)) {
  cat("\nHorsepower summary:\n")
  # Convert to numeric for summary
  hp_numeric <- as.numeric(engine_df$HORSEPOWER)
  cat("Horsepower range:", min(hp_numeric, na.rm = TRUE), "to", max(hp_numeric, na.rm = TRUE), "\n")
  cat("Average horsepower:", round(mean(hp_numeric, na.rm = TRUE), 2), "\n")
  cat("Median horsepower:", median(hp_numeric, na.rm = TRUE), "\n")
}

# Check for thrust information
if ("THRUST" %in% names(engine_df)) {
  cat("\nThrust summary:\n")
  # Convert to numeric for summary
  thrust_numeric <- as.numeric(engine_df$THRUST)
  cat("Thrust range:", min(thrust_numeric, na.rm = TRUE), "to", max(thrust_numeric, na.rm = TRUE), "\n")
  cat("Average thrust:", round(mean(thrust_numeric, na.rm = TRUE), 2), "\n")
  cat("Median thrust:", median(thrust_numeric, na.rm = TRUE), "\n")
}

# Look for any date columns
date_cols <- names(engine_df)[grepl("DATE", toupper(names(engine_df)))]
if (length(date_cols) > 0) {
  cat("\nDate columns found:", paste(date_cols, collapse = ", "), "\n")
  for (col in date_cols) {
    cat("Sample values for", col, ":\n")
    sample_dates <- unique(engine_df[[col]])[1:5]
    for (date_val in sample_dates) {
      cat("  -", date_val, "\n")
    }
  }
}

# Clean up extra column if it exists
if ("...7" %in% names(engine_df)) {
  cat("\nRemoving empty extra column (...7)\n")
  engine_df <- engine_df %>%
    select(-`...7`)
}

# Check for missing values
cat("\nMissing value analysis:\n")
missing_summary <- engine_df %>%
  summarise_all(~sum(is.na(.) | . == "" | . == " ")) %>%
  gather(key = "column", value = "missing_count") %>%
  arrange(desc(missing_count))

print(missing_summary)

# Show some sample records with complete data
cat("\nSample complete records:\n")
complete_records <- engine_df %>%
  filter(complete.cases(.))

if (nrow(complete_records) > 0) {
  cat("Found", nrow(complete_records), "complete records\n")
  print(head(complete_records, 3))
} else {
  cat("No completely filled records found\n")
}

# Clean up column names - make them MySQL-friendly
original_names <- names(engine_df)
new_names <- original_names %>%
  tolower() %>%                    # Convert to lowercase
  gsub("-", "_", .) %>%            # Replace hyphens with underscores
  gsub(" ", "_", .) %>%            # Replace spaces with underscores
  gsub("__+", "_", .) %>%          # Replace multiple underscores with single
  gsub("^_|_$", "", .) %>%         # Remove leading/trailing underscores
  gsub("^[0-9]", "col_\\1", .)     # Prefix numeric column names with 'col_'

# Apply the new names
names(engine_df) <- new_names

cat("Column names tidied for MySQL compatibility:\n")
for (i in seq_along(original_names)) {
  cat(sprintf("  %s -> %s\n", original_names[i], new_names[i]))
}

# Function to escape SQL strings and handle NULL values
escape_sql_string <- function(x) {
  if (is.na(x) || x == "" || x == " " || x == "NULL") {
    return("NULL")
  } else {
    # Escape single quotes and backslashes
    escaped <- gsub("'", "''", x)  # Escape single quotes
    escaped <- gsub("\\\\", "\\\\\\\\", escaped)  # Escape backslashes
    return(paste0("'", escaped, "'"))
  }
}

# Function to determine appropriate MySQL data types
get_mysql_type <- function(col_name, data) {
  # Check if column contains only numeric data
  numeric_data <- data[!is.na(data) & data != "" & data != " "]
  if (length(numeric_data) > 0) {
    is_numeric <- all(grepl("^[0-9.-]+$", numeric_data))
    if (is_numeric) {
      # Check if it's an integer or decimal
      has_decimal <- any(grepl("\\.", numeric_data))
      max_length <- max(nchar(numeric_data))
      
      if (has_decimal) {
        return(paste0("DECIMAL(", max_length + 2, ",2)"))
      } else {
        if (max_length <= 3) return("SMALLINT")
        if (max_length <= 5) return("INT")
        if (max_length <= 10) return("BIGINT")
        return(paste0("VARCHAR(", max_length, ")"))
      }
    }
  }
  
  # Check if it's a date column
  if (grepl("date", tolower(col_name))) {
    return("DATE")
  }
  
  # Default to VARCHAR with appropriate length
  max_length <- max(nchar(data[!is.na(data) & data != "" & data != " "]), default = 0)
  if (max_length == 0) max_length <- 1
  return(paste0("VARCHAR(", min(max_length * 2, 255), ")"))
}

# Generate CREATE TABLE statement
cat("\nGenerating SQL CREATE TABLE statement...\n")

# Generate column definitions
column_defs <- character()
for (col in names(engine_df)) {
  mysql_type <- get_mysql_type(col, engine_df[[col]])
  column_defs <- c(column_defs, paste0("  `", col, "` ", mysql_type))
}

create_table_sql <- paste0(
  "-- CREATE TABLE statement for engines data\n",
  "-- Generated for MySQL 8.0\n\n",
  "DROP TABLE IF EXISTS `engines`;\n",
  "CREATE TABLE `engines` (\n",
  "  `id` INT AUTO_INCREMENT PRIMARY KEY,\n",
  paste(column_defs, collapse = ",\n"),
  "\n);\n\n"
)

# Generate INSERT statements
cat("Generating INSERT statements...\n")

# Process data in batches to avoid memory issues
batch_size <- 1000
total_rows <- nrow(engine_df)
num_batches <- ceiling(total_rows / batch_size)

# Prepare column names for INSERT
column_names <- paste0("`", names(engine_df), "`", collapse = ", ")
insert_header <- paste0("INSERT INTO `engines` (", column_names, ") VALUES\n")

# Start building the SQL file content
sql_content <- create_table_sql

cat("Processing", total_rows, "rows in", num_batches, "batches...\n")

for (batch_num in 1:num_batches) {
  start_row <- (batch_num - 1) * batch_size + 1
  end_row <- min(batch_num * batch_size, total_rows)
  
  cat("Processing batch", batch_num, "of", num_batches, "(rows", start_row, "-", end_row, ")\n")
  
  batch_data <- engine_df[start_row:end_row, ]
  
  # Generate VALUES for this batch
  values_list <- character()
  for (i in 1:nrow(batch_data)) {
    row_values <- sapply(batch_data[i, ], escape_sql_string)
    values_list <- c(values_list, paste0("(", paste(row_values, collapse = ", "), ")"))
  }
  
  # Add batch to SQL content
  batch_sql <- paste0(insert_header, paste(values_list, collapse = ",\n"), ";\n\n")
  sql_content <- paste0(sql_content, batch_sql)
}

# Write the complete SQL file
sql_output_file <- "engines_import.sql"
cat("Writing SQL file to:", sql_output_file, "\n")

writeLines(sql_content, sql_output_file)

# Also save as CSV for backup
csv_output_file <- paste0(
  "engine_clean.csv"
)
cat("Saving CSV backup to:", csv_output_file, "\n")
write_csv(engine_df, csv_output_file)

# Generate summary statistics
cat("\nFiles generated successfully!\n")
cat("SQL file size:", file.info(sql_output_file)$size, "bytes\n")
cat("Total rows:", total_rows, "\n")
cat("Columns:", ncol(engine_df), "\n")

# Show column information
cat("\nColumn information:\n")
for (col in names(engine_df)) {
  mysql_type <- get_mysql_type(col, engine_df[[col]])
  non_null_count <- sum(!is.na(engine_df[[col]]) & engine_df[[col]] != "" & engine_df[[col]] != " ")
  cat(sprintf("  %-20s %-20s (%d non-null values)\n", col, mysql_type, non_null_count))
}

cat("\nTo import into MySQL 8, use:\n")
cat("mysql -u your_username -p your_database < ", sql_output_file, "\n")

cat("\nOr from within MySQL:\n")
cat("SOURCE ", sql_output_file, ";\n")


sql import

-- FAA Aircraft Data Import Scripts (Fixed for SQL files)
-- This version uses SQL import files from /data/clean
-- Database: faa_aircraft_four_db
-- Source files from: /data/clean

-- Create the database
CREATE DATABASE IF NOT EXISTS faa_aircraft_four_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE faa_aircraft_four_db;

-- Import aircraft_reference_import.sql (Aircraft Reference)
SOURCE aircraft_reference_import.sql;

-- Import engines_import.sql (Engine Specifications)
SOURCE engines_import.sql;

-- Import dealers_import.sql (Aircraft Dealers)
SOURCE dealers_import.sql;

-- Import aircraft_master_import.sql (Main Aircraft Registry)
SOURCE aircraft_master_import.sql;

-- Import deregistered_aircraft_import.sql (Deregistered Aircraft)
SOURCE deregistered_aircraft_import.sql;

-- Import documentation_index_import.sql (Documentation Index)
SOURCE documentation_index_import.sql;

-- Import reserved_numbers_import.sql (Reserved N-Numbers)
SOURCE reserved_numbers_import.sql;

-- Verify import results
SELECT 'aircraft_reference' as table_name, COUNT(*) as record_count FROM aircraft_reference
UNION ALL
SELECT 'engines', COUNT(*) FROM engines
UNION ALL
SELECT 'dealers', COUNT(*) FROM dealers
UNION ALL
SELECT 'aircraft_master', COUNT(*) FROM aircraft_master
UNION ALL
SELECT 'deregistered_aircraft', COUNT(*) FROM deregistered_aircraft
UNION ALL
SELECT 'documentation_index', COUNT(*) FROM documentation_index
UNION ALL
SELECT 'reserved_numbers', COUNT(*) FROM reserved_numbers;

SELECT 'Import completed successfully!' as status;

index

And then indexes were applied to the fields in each table using

-- Add indexes to FAA Aircraft Database for better performance
-- Updated for faa_aircraft_four_db with correct field names

USE faa_aircraft_four_db;

-- Indexes for aircraft_master table
CREATE INDEX idx_n_number ON aircraft_master(n_number);
CREATE INDEX idx_serial_number ON aircraft_master(serial_number);
CREATE INDEX idx_mfr_mdl_code ON aircraft_master(mfr_mdl_code);
CREATE INDEX idx_state ON aircraft_master(state);
CREATE INDEX idx_name ON aircraft_master(name);
CREATE INDEX idx_year_mfr ON aircraft_master(year_mfr);
CREATE INDEX idx_city ON aircraft_master(city);
CREATE INDEX idx_country ON aircraft_master(country);
CREATE INDEX idx_type_aircraft ON aircraft_master(type_aircraft);
CREATE INDEX idx_type_engine ON aircraft_master(type_engine);
CREATE INDEX idx_status_code ON aircraft_master(status_code);

-- Indexes for aircraft_reference table
CREATE INDEX idx_mfr ON aircraft_reference(mfr);
CREATE INDEX idx_model ON aircraft_reference(model);
CREATE INDEX idx_code ON aircraft_reference(code);

-- Indexes for engines table
CREATE INDEX idx_code ON engines(code);
CREATE INDEX idx_mfr ON engines(mfr);
CREATE INDEX idx_model ON engines(model);
CREATE INDEX idx_type ON engines(type);

-- Indexes for dealers table
CREATE INDEX idx_certificate_number ON dealers(certificate_number);
CREATE INDEX idx_name ON dealers(name);
CREATE INDEX idx_city ON dealers(city);
CREATE INDEX idx_state_abbrev ON dealers(state_abbrev);

-- Indexes for deregistered_aircraft table
CREATE INDEX idx_n_number ON deregistered_aircraft(n_number);
CREATE INDEX idx_serial_number ON deregistered_aircraft(serial_number);
CREATE INDEX idx_mfr_mdl_code ON deregistered_aircraft(mfr_mdl_code);
CREATE INDEX idx_name ON deregistered_aircraft(name);
CREATE INDEX idx_city_mail ON deregistered_aircraft(city_mail);
CREATE INDEX idx_state_abbrev_mail ON deregistered_aircraft(state_abbrev_mail);
CREATE INDEX idx_year_mfr ON deregistered_aircraft(year_mfr);

-- Indexes for documentation_index table
CREATE INDEX idx_collateral ON documentation_index(collateral);
CREATE INDEX idx_doc_id ON documentation_index(doc_id);
CREATE INDEX idx_serial_id ON documentation_index(serial_id);
CREATE INDEX idx_doc_type ON documentation_index(doc_type);

-- Indexes for reserved_numbers table
CREATE INDEX idx_n_number ON reserved_numbers(n_number);
CREATE INDEX idx_registrant ON reserved_numbers(registrant);
CREATE INDEX idx_city ON reserved_numbers(city);
CREATE INDEX idx_state ON reserved_numbers(state);

-- Show all indexes created
SHOW INDEX FROM aircraft_master;
SHOW INDEX FROM aircraft_reference;
SHOW INDEX FROM engines;
SHOW INDEX FROM dealers;
SHOW INDEX FROM deregistered_aircraft;
SHOW INDEX FROM documentation_index;
SHOW INDEX FROM reserved_numbers;

SELECT 'All indexes created successfully!' as status;

Data Analysis & Findings

This section presents a comprehensive analysis of the FAA aircraft registration database using SQL queries and data visualizations. The analysis covers database structure, key statistics, and insights derived from the data.

Analysis Methodology

All queries were executed against a local MySQL 8.0 database containing the complete FAA aircraft registration dataset. Results are presented with both raw data and visual interpretations where applicable.

Database Overview

1. Database Structure & Metadata

Database Information

The FAA aircraft database contains 7 main tables with comprehensive aircraft registration and reference data:

-- Database listing
SHOW DATABASES;

Active Database: faa_aircraft_four_db

Table Structure & Statistics

-- Table overview with row counts and storage information
SELECT 
    TABLE_NAME,
    TABLE_TYPE,
    ENGINE,
    TABLE_ROWS,
    ROUND(DATA_LENGTH/1024/1024, 2) as DATA_SIZE_MB,
    ROUND(INDEX_LENGTH/1024/1024, 2) as INDEX_SIZE_MB
FROM information_schema.TABLES 
WHERE TABLE_SCHEMA = DATABASE()
ORDER BY TABLE_ROWS DESC;
Table Name Type Engine Rows Data Size (MB) Index Size (MB)
deregistered_aircraft BASE TABLE InnoDB 359,778 61.6 0.0
aircraft_master BASE TABLE InnoDB 302,049 60.6 0.0
reserved_numbers BASE TABLE InnoDB 128,292 14.5 0.0
aircraft_reference BASE TABLE InnoDB 93,503 8.5 0.0
dealers BASE TABLE InnoDB 11,743 1.5 0.0
documentation_index BASE TABLE InnoDB 9,715 1.5 0.0
engines BASE TABLE InnoDB 4,708 0.3 0.0

Database Size Summary

  • Total Records: 910,788 across all tables
  • Total Storage: ~148.5 MB of data
  • Primary Focus: Aircraft master (302K records) and deregistered aircraft (360K records)

List indexes

mysql> SELECT -> TABLE_NAME, -> COLUMN_NAME, -> INDEX_NAME, -> NON_UNIQUE, -> SEQ_IN_INDEX -> FROM information_schema.STATISTICS -> WHERE TABLE_SCHEMA = DATABASE() -> ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;

+-----------------------+--------------------+------------------------+------------+--------------+
|TABLE_NAME            | COLUMN_NAME        | INDEX_NAME             | NON_UNIQUE | SEQ_IN_INDEX |
+-----------------------+--------------------+------------------------+------------+--------------+
|aircraft_master       | city               | idx_city               |          1 |            1 |
|aircraft_master       | country            | idx_country            |          1 |            1 |
|aircraft_master       | mfr_mdl_code       | idx_mfr_mdl_code       |          1 |            1 |
|aircraft_master       | n_number           | idx_n_number           |          1 |            1 |
|aircraft_master       | name               | idx_name               |          1 |            1 |
|aircraft_master       | serial_number      | idx_serial_number      |          1 |            1 |
|aircraft_master       | state              | idx_state              |          1 |            1 |
|aircraft_master       | status_code        | idx_status_code        |          1 |            1 |
|aircraft_master       | type_aircraft      | idx_type_aircraft      |          1 |            1 |
|aircraft_master       | type_engine        | idx_type_engine        |          1 |            1 |
|aircraft_master       | year_mfr           | idx_year_mfr           |          1 |            1 |
|aircraft_master       | id                 | PRIMARY                |          0 |            1 |
|aircraft_reference    | code               | idx_code               |          1 |            1 |
|aircraft_reference    | mfr                | idx_mfr                |          1 |            1 |
|aircraft_reference    | model              | idx_model              |          1 |            1 |
|aircraft_reference    | id                 | PRIMARY                |          0 |            1 |
|dealers               | certificate_number | idx_certificate_number |          1 |            1 |
|dealers               | city               | idx_city               |          1 |            1 |
|dealers               | name               | idx_name               |          1 |            1 |
|dealers               | state_abbrev       | idx_state_abbrev       |          1 |            1 |
|dealers               | id                 | PRIMARY                |          0 |            1 |
|deregistered_aircraft | city_mail          | idx_city_mail          |          1 |            1 |
|deregistered_aircraft | mfr_mdl_code       | idx_mfr_mdl_code       |          1 |            1 |
|deregistered_aircraft | n_number           | idx_n_number           |          1 |            1 |
|deregistered_aircraft | name               | idx_name               |          1 |            1 |
|deregistered_aircraft | serial_number      | idx_serial_number      |          1 |            1 |
|deregistered_aircraft | state_abbrev_mail  | idx_state_abbrev_mail  |          1 |            1 |
|deregistered_aircraft | year_mfr           | idx_year_mfr           |          1 |            1 |
|deregistered_aircraft | id                 | PRIMARY                |          0 |            1 |
|documentation_index   | collateral         | idx_collateral         |          1 |            1 |
|documentation_index   | doc_id             | idx_doc_id             |          1 |            1 |
|documentation_index   | doc_type           | idx_doc_type           |          1 |            1 |
|documentation_index   | serial_id          | idx_serial_id          |          1 |            1 |
|documentation_index   | id                 | PRIMARY                |          0 |            1 |
|engines               | code               | idx_code               |          1 |            1 |
|engines               | mfr                | idx_mfr                |          1 |            1 |
|engines               | model              | idx_model              |          1 |            1 |
|engines               | type               | idx_type               |          1 |            1 |
|engines               | id                 | PRIMARY                |          0 |            1 |
|reserved_numbers      | city               | idx_city               |          1 |            1 |
|reserved_numbers      | n_number           | idx_n_number           |          1 |            1 |
|reserved_numbers      | registrant         | idx_registrant         |          1 |            1 |
|reserved_numbers      | state              | idx_state              |          1 |            1 |
|reserved_numbers      | id                 | PRIMARY                |          0 |            1 |
+-----------------------+--------------------+------------------------+------------+--------------+
44 rows in set (0.01 sec)

Table data

mysql> SHOW TABLE STATUS\G;
*************************** 1. row ***************************
           Name: aircraft_master
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 302049
 Avg_row_length: 210
    Data_length: 63537152
Max_data_length: 0
   Index_length: 0
      Data_free: 4194304
 Auto_increment: 306404
    Create_time: 2025-09-14 17:01:57
    Update_time: 2025-09-14 16:38:46
     Check_time: NULL
      Collation: utf8mb4_unicode_ci
       Checksum: NULL
 Create_options: 
        Comment: 
*************************** 2. row ***************************
           Name: aircraft_reference
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 93503
 Avg_row_length: 95
    Data_length: 8929280
Max_data_length: 0
   Index_length: 0
      Data_free: 2097152
 Auto_increment: 93126
    Create_time: 2025-09-14 17:01:57
    Update_time: 2025-09-14 16:38:42
     Check_time: NULL
      Collation: utf8mb4_unicode_ci
       Checksum: NULL
 Create_options: 
        Comment: 
*************************** 3. row ***************************
           Name: dealers
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 11743
 Avg_row_length: 135
    Data_length: 1589248
Max_data_length: 0
   Index_length: 0
      Data_free: 3145728
 Auto_increment: 12193
    Create_time: 2025-09-14 17:01:57
    Update_time: 2025-09-14 16:38:42
     Check_time: NULL
      Collation: utf8mb4_unicode_ci
       Checksum: NULL
 Create_options: 
        Comment: 
*************************** 4. row ***************************
           Name: deregistered_aircraft
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 359778
 Avg_row_length: 179
    Data_length: 64585728
Max_data_length: 0
   Index_length: 0
      Data_free: 2097152
 Auto_increment: 380963
    Create_time: 2025-09-14 17:01:59
    Update_time: 2025-09-14 16:38:52
     Check_time: NULL
      Collation: utf8mb4_unicode_ci
       Checksum: NULL
 Create_options: 
        Comment: 
*************************** 5. row ***************************
           Name: documentation_index
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 9715
 Avg_row_length: 163
    Data_length: 1589248
Max_data_length: 0
   Index_length: 0
      Data_free: 3145728
 Auto_increment: 9541
    Create_time: 2025-09-14 17:01:59
    Update_time: 2025-09-14 16:38:52
     Check_time: NULL
      Collation: utf8mb4_unicode_ci
       Checksum: NULL
 Create_options: 
        Comment: 
*************************** 6. row ***************************
           Name: engines
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 4708
 Avg_row_length: 73
    Data_length: 344064
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 4729
    Create_time: 2025-09-14 17:01:57
    Update_time: 2025-09-14 16:38:42
     Check_time: NULL
      Collation: utf8mb4_unicode_ci
       Checksum: NULL
 Create_options: 
        Comment: 
*************************** 7. row ***************************
           Name: reserved_numbers
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 128292
 Avg_row_length: 118
    Data_length: 15220736
Max_data_length: 0
   Index_length: 0
      Data_free: 5242880
 Auto_increment: 128308
    Create_time: 2025-09-14 17:01:59
    Update_time: 2025-09-14 16:38:52
     Check_time: NULL
      Collation: utf8mb4_unicode_ci
       Checksum: NULL
 Create_options: 
        Comment: 
7 rows in set (0.00 sec)

Table Size & Structure Overview

mysql> SELECT 
    TABLE_NAME as 'Table Name',
    ENGINE as 'Engine',
    ROUND(DATA_LENGTH / 1024 / 1024, 2) AS 'Data Size (MB)',
    ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS 'Index Size (MB)',
    ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS 'Total Size (MB)',
    TABLE_ROWS as 'Approx Rows',
    ROUND((DATA_LENGTH + INDEX_LENGTH) / TABLE_ROWS, 0) AS 'Bytes per Row',
    CREATE_TIME as 'Created',
    UPDATE_TIME as 'Last Updated'
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_SCHEMA = 'faa_aircraft_db'
ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC\G;

************************** 1. row ***************************
     Table Name: aircraft_master
         Engine: InnoDB
 Data Size (MB): 73.63
Index Size (MB): 77.70
Total Size (MB): 151.33
    Approx Rows: 300490
  Bytes per Row: 528
        Created: 2025-09-10 18:42:19
   Last Updated: NULL
*************************** 2. row ***************************
     Table Name: deregistered_aircraft
         Engine: InnoDB
 Data Size (MB): 76.63
Index Size (MB): 0.00
Total Size (MB): 76.63
    Approx Rows: 371163
  Bytes per Row: 216
        Created: 2025-09-10 20:57:54
   Last Updated: NULL
*************************** 3. row ***************************
     Table Name: reserved_numbers
         Engine: InnoDB
 Data Size (MB): 18.55
Index Size (MB): 0.00
Total Size (MB): 18.55
    Approx Rows: 121334
  Bytes per Row: 160
        Created: 2025-09-10 00:44:58
   Last Updated: NULL
*************************** 4. row ***************************
     Table Name: aircraft_reference
         Engine: InnoDB
 Data Size (MB): 11.52
Index Size (MB): 0.00
Total Size (MB): 11.52
    Approx Rows: 92809
  Bytes per Row: 130
        Created: 2025-09-10 00:44:39
   Last Updated: NULL
*************************** 5. row ***************************
     Table Name: dealers
         Engine: InnoDB
 Data Size (MB): 2.52
Index Size (MB): 0.00
Total Size (MB): 2.52
    Approx Rows: 12030
  Bytes per Row: 219
        Created: 2025-09-10 00:44:40
   Last Updated: NULL
*************************** 6. row ***************************
     Table Name: documentation_index
         Engine: InnoDB
 Data Size (MB): 2.52
Index Size (MB): 0.00
Total Size (MB): 2.52
    Approx Rows: 22064
  Bytes per Row: 120
        Created: 2025-09-10 00:44:58
   Last Updated: NULL
*************************** 7. row ***************************
     Table Name: engines
         Engine: InnoDB
 Data Size (MB): 0.48
Index Size (MB): 0.00
Total Size (MB): 0.48
    Approx Rows: 4602
  Bytes per Row: 110
        Created: 2025-09-10 00:44:39
   Last Updated: NULL
7 rows in set (0.01 sec)

Column count by table

mysql> SELECT TABLE_NAME as ‘Table Name’, COUNT() as ‘Column Count’ FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = ‘faa_aircraft_db’ GROUP BY TABLE_NAME ORDER BY COUNT() DESC;

+-----------------------+--------------+
|Table Name            | Column Count |
+-----------------------+--------------+
|deregistered_aircraft |           40 |
|aircraft_master       |           35 |
|dealers               |           26 |
|aircraft_reference    |           14 |
|reserved_numbers      |           13 |
|documentation_index   |           10 |
|engines               |            7 |
+-----------------------+--------------+
7 rows in set (0.01 sec)

Database summary

mysql> SELECT ‘TOTAL DATABASE SUMMARY’ as ‘Metric’, ROUND(SUM((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024), 2) AS ‘Total Size (MB)’, SUM(TABLE_ROWS) as ‘Total Approx Rows’, COUNT(*) as ‘Total Tables’ FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ‘faa_aircraft_four_db’;

+------------------------+-----------------+-------------------+--------------+
|Metric                 | Total Size (MB) | Total Approx Rows | Total Tables |
+------------------------+-----------------+-------------------+--------------+
|TOTAL DATABASE SUMMARY |          148.58 |            909788 |            7 |
+------------------------+-----------------+-------------------+--------------+
1 row in set (0.00 sec)

Aircraft Master Table Analysis

The aircraft_master table is the core of the FAA database, containing detailed registration information for all currently registered aircraft in the United States.

Table Schema & Structure

mysql> DESCRIBE aircraft_master;

+------------------+--------------+------+-----+---------+----------------+
|Field            | Type         | Null | Key | Default | Extra          |
+------------------+--------------+------+-----+---------+----------------+
|id               | int          | NO   | PRI | NULL    | auto_increment |
|n_number         | varchar(10)  | YES  | MUL | NULL    |                |
|serial_number    | varchar(60)  | YES  | MUL | NULL    |                |
|mfr_mdl_code     | varchar(14)  | YES  | MUL | NULL    |                |
|eng_mfr_mdl      | int          | YES  |     | NULL    |                |
|year_mfr         | int          | YES  | MUL | NULL    |                |
|type_registrant  | smallint     | YES  |     | NULL    |                |
|name             | varchar(100) | YES  | MUL | NULL    |                |
|street           | varchar(66)  | YES  |     | NULL    |                |
|street2          | varchar(66)  | YES  |     | NULL    |                |
|city             | varchar(36)  | YES  | MUL | NULL    |                |
|state            | varchar(4)   | YES  | MUL | NULL    |                |
|zip_code         | varchar(20)  | YES  |     | NULL    |                |
|region           | varchar(2)   | YES  |     | NULL    |                |
|county           | smallint     | YES  |     | NULL    |                |
|country          | varchar(4)   | YES  | MUL | NULL    |                |
|last_action_date | bigint       | YES  |     | NULL    |                |
|cert_issue_date  | bigint       | YES  |     | NULL    |                |
|certification    | varchar(20)  | YES  |     | NULL    |                |
|type_aircraft    | varchar(2)   | YES  | MUL | NULL    |                |
|type_engine      | smallint     | YES  | MUL | NULL    |                |
|status_code      | varchar(4)   | YES  | MUL | NULL    |                |
|mode_s_code      | bigint       | YES  |     | NULL    |                |
|fract_owner      | varchar(2)   | YES  |     | NULL    |                |
|air_worth_date   | bigint       | YES  |     | NULL    |                |
|other_names(1)   | varchar(100) | YES  |     | NULL    |                |
|other_names(2)   | varchar(98)  | YES  |     | NULL    |                |
|other_names(3)   | varchar(98)  | YES  |     | NULL    |                |
|other_names(4)   | varchar(88)  | YES  |     | NULL    |                |
|other_names(5)   | varchar(94)  | YES  |     | NULL    |                |
|expiration_date  | bigint       | YES  |     | NULL    |                |
|unique_id        | bigint       | YES  |     | NULL    |                |
|kit_mfr          | varchar(60)  | YES  |     | NULL    |                |
|kit_model        | varchar(40)  | YES  |     | NULL    |                |
|mode_s_code_hex  | varchar(12)  | YES  |     | NULL    |                |
|...35            | varchar(2)   | YES  |     | NULL    |                |
+------------------+--------------+------+-----+---------+----------------+
36 rows in set (0.00 sec)

Table indexes

mysql> SHOW INDEX FROM aircraft_master\G
*************************** 1. row ***************************
        Table: aircraft_master
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 302049
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
      Visible: YES
   Expression: NULL
*************************** 2. row ***************************
        Table: aircraft_master
   Non_unique: 1
     Key_name: idx_n_number
 Seq_in_index: 1
  Column_name: n_number
    Collation: A
  Cardinality: 302049
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
      Visible: YES
   Expression: NULL
   
*************************** 3. row *************************** and so on

Key Insights & Analysis

Geographic Distribution of Aircraft

-- Top 10 states by aircraft registration count
SELECT 
    state, 
    COUNT(*) as aircraft_count,
    ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM aircraft_master), 2) as percentage
FROM aircraft_master 
WHERE state IS NOT NULL
GROUP BY state 
ORDER BY aircraft_count DESC 
LIMIT 10;
State Aircraft Count Percentage of Total
TX 28,614 9.47%
CA 25,123 8.32%
FL 21,217 7.02%
DE 10,962 3.63%
WA 10,103 3.35%
AK 9,076 3.01%
GA 8,597 2.85%
UT 8,468 2.80%
AZ 8,303 2.75%
OH 8,113 2.69%

Geographic Insights

  • Texas leads with nearly 10% of all US aircraft registrations
  • Top 3 states (TX, CA, FL) account for 24.8% of all registrations
  • Delaware ranks surprisingly high, likely due to corporate registrations

Aircraft Manufacturers Analysis

-- Top aircraft manufacturers by model count
SELECT 
    mfr as manufacturer,
    COUNT(*) as model_count,
    ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM aircraft_reference), 2) as percentage
FROM aircraft_reference 
GROUP BY mfr 
ORDER BY model_count DESC 
LIMIT 10;
Manufacturer Model Count Percentage
BOEING 1,541 1.65%
CESSNA 419 0.45%
BEECH 336 0.36%
PIPER 261 0.28%
DOUGLAS 240 0.26%
LOCKHEED 221 0.24%
SIKORSKY 197 0.21%
BELL 161 0.17%
DJI 159 0.17%
DEHAVILLAND 151 0.16%

Manufacturing Landscape

  • Boeing dominates with 1,541 different aircraft models/types
  • General Aviation manufacturers (Cessna, Beech, Piper) show strong presence
  • Helicopter manufacturers (Sikorsky, Bell) are well-represented
  • Drone technology (DJI) is emerging in the database
– Find Aircraft by N-Number (Clean Format)

mysql> SELECT n_number AS ‘N-Number’, name AS ‘Owner’, city AS ‘City’, state AS ‘State’, year_mfr AS ‘Year’, mfr_mdl_code AS ‘Model_Code’ FROM aircraft_master WHERE n_number = ‘10004’;

+----------+--------------+------------+-------+------+------------+
|N-Number | Owner        | City       | State | Year | Model_Code |
+----------+--------------+------------+-------+------+------------+
|10004    | ETOS AIR LLC | NEW LONDON | TX    | NULL | 2072738    |
+----------+--------------+------------+-------+------+------------+
1 row in set (0.00 sec)
– Find Aircraft by N-Number (full record)
mysql> SELECT * FROM aircraft_master WHERE n_number = '10004'\G
*************************** 1. row ***************************
              id: 4
        n_number: 10004
   serial_number: T18208245
    mfr_mdl_code: 2072738
     eng_mfr_mdl: NULL
        year_mfr: NULL
 type_registrant: 7
            name: ETOS AIR LLC
          street: PO BOX 288
         street2: NULL
            city: NEW LONDON
           state: TX
        zip_code: 756820288
          region: 2
          county: 401
         country: US
last_action_date: 20230722
 cert_issue_date: 20130312
   certification: NULL
   type_aircraft: 4
     type_engine: 2
     status_code: V
     mode_s_code: 50003451
     fract_owner: NULL
  air_worth_date: NULL
  other_names(1): NULL
  other_names(2): NULL
  other_names(3): NULL
  other_names(4): NULL
  other_names(5): NULL
 expiration_date: 20290331
       unique_id: 102879
         kit_mfr: NULL
       kit_model: NULL
 mode_s_code_hex: A00729
           ...35: NULL
1 row in set (0.00 sec)
– Top 5 Aircraft Records

mysql> SELECT n_number AS ‘N-Number’, name AS ‘Owner’, city AS ‘City’, state AS ‘State’, year_mfr AS ‘Year’, mfr_mdl_code AS ‘Model_Code’ FROM aircraft_master WHERE n_number IS NOT NULL LIMIT 5;

+----------+------------------------------+------------+-------+------+------------+
|N-Number | Owner                        | City       | State | Year | Model_Code |
+----------+------------------------------+------------+-------+------+------------+
|100      | BENE MARY D                  | KETCHUM    | OK    | 1940 | 7100510    |
|10000    | 9AT LLC                      | NASHVILLE  | TN    | NULL | 2130004    |
|10001    | STOOS ROBERT A               | LAKELAND   | FL    | 1928 | 9601202    |
|10004    | ETOS AIR LLC                 | NEW LONDON | TX    | NULL | 2072738    |
|10006    | COUTCHES ROBERT HERCULES DBA | LIVERMORE  | CA    | 1955 | 1152020    |
+----------+------------------------------+------------+-------+------+------------+
5 rows in set (0.00 sec)
– Aircraft by country

mysql> SELECT country, COUNT(*) as count FROM aircraft_master GROUP BY country ORDER BY count DESC;

+---------+--------+
|country | count  |
+---------+--------+
|US      | 301955 |
|NULL    |   2376 |
|GB      |    761 |
|RQ      |    482 |
|DE      |    331 |
|AT      |    100 |
|VI      |     94 |
|GU      |     65 |
|CA      |     47 |
|MP      |     31 |
|CH      |     17 |
|MX      |     12 |
|IE      |     11 |
|FR      |      9 |
|BS      |      8 |
|PL      |      8 |
|SA      |      7 |
|HR      |      7 |
|PA      |      7 |
|GR      |      6 |
|TH      |      5 |
|BE      |      5 |
|AU      |      4 |
|JP      |      4 |
|NZ      |      4 |
|DO      |      3 |
|KY      |      3 |
|TC      |      3 |
|SE      |      2 |
|ES      |      2 |
|UA      |      2 |
|DK      |      2 |
|PH      |      2 |
|ZA      |      2 |
|JE      |      2 |
|NL      |      2 |
|MY      |      2 |
|IT      |      1 |
|MD      |      1 |
|NF      |      1 |
|NG      |      1 |
|LV      |      1 |
|LU      |      1 |
|KE      |      1 |
|IL      |      1 |
|HK      |      1 |
|PW      |      1 |
|GY      |      1 |
|FM      |      1 |
|FI      |      1 |
|BW      |      1 |
|BR      |      1 |
|AS      |      1 |
|AN      |      1 |
|AI      |      1 |
|AG      |      1 |
|ZW      |      1 |
+---------+--------+
57 rows in set (0.06 sec)
– Aircraft manufactured by decade

This query groups aircraft by decade (e.g., “2020s”, “2010s”, “1990s”) and counts how many aircraft were manufactured in each decade.

mysql> SELECT decade, COUNT() as count FROM ( SELECT CONCAT(FLOOR(year_mfr/10)10, ‘s’) as decade FROM aircraft_master WHERE year_mfr IS NOT NULL ) as decades GROUP BY decade ORDER BY decade DESC;

+--------+-------+
|decade | count |
+--------+-------+
|2020s  | 18817 |
|2010s  | 27299 |
|2000s  | 36620 |
|1990s  | 17804 |
|1980s  | 17763 |
|1970s  | 49584 |
|1960s  | 37371 |
|1950s  | 16148 |
|1940s  | 20882 |
|1930s  |  1599 |
|1920s  |   405 |
|1910s  |    32 |
|1900s  |     1 |
|0s     |   151 |
+--------+-------+
14 rows in set (0.11 sec)
– Distribution of Type Aircraft codes

Description: Counts of each Type Aircraft code present in aircraft_master.

mysql> SELECT type_aircraft, COUNT(*) AS count FROM aircraft_master WHERE type_aircraft IS NOT NULL GROUP BY type_aircraft ORDER BY type_aircraft;

+---------------+--------+
|type_aircraft | count  |
+---------------+--------+
|1             |   4842 |
|2             |   5179 |
|3             |     49 |
|4             | 218584 |
|5             |  48847 |
|6             |  24588 |
|7             |   1046 |
|8             |   1902 |
|9             |    376 |
|H             |    969 |
|O             |     21 |
+---------------+--------+
11 rows in set (0.06 sec)

3. aircraft_reference table

Sample queries

– Top 5 Aircraft Specifications

mysql> SELECT mfr AS ‘Manufacturer’, model AS ‘Model’, type_acft AS ‘Type’, no_eng AS ‘Engines’, no_seats AS ‘Seats’ FROM aircraft_reference WHERE mfr IS NOT NULL LIMIT 5;

+--------------------------+-------------------+------+---------+-------+
|Manufacturer             | Model             | Type | Engines | Seats |
+--------------------------+-------------------+------+---------+-------+
|101 FLYING ASSOC INC     | THORP T-18        | 4    |       1 |     2 |
|107.5 FLYING CORPORATION | ONE DESIGN DR 107 | 4    |       1 |     1 |
|131MH LLC                | CCX-1865          | 4    |       1 |     2 |
|17633 INC                | 162F              | 6    |       1 |     2 |
|177MF LLC                | PITTS MODEL 12    | 4    |       1 |     2 |
+--------------------------+-------------------+------+---------+-------+
5 rows in set (0.01 sec)
– Aircraft reference details for the matched aircraft

Description: Retrieves specifications for the aircraft model associated with serial number 42626.

mysql> SELECT ar.code, ar.mfr, ar.model, ar.type_acft, ar.ac_cat, ar.no_eng, ar.ac_weight, ar.no_seats, ar.speed FROM aircraft_reference ar WHERE ar.code = (SELECT mfr_mdl_code FROM aircraft_master WHERE serial_number = ‘42626’)

************************** 1. row ***************************
     code: 13845FZ
      mfr: BOEING
    model: 737-8
type_acft: 5
   ac_cat: 1
   no_eng: 2
ac_weight: CLASS 3
 no_seats: 175
    speed: 0
1 row in set (0.00 sec)

4. engines table

Sample queries

– Top 5 Engine Specifications

mysql> SELECT mfr AS ‘Manufacturer’, model AS ‘Model’, type AS ‘Type’, horsepower AS ‘HP’, thrust AS ‘Thrust’ FROM engines WHERE mfr IS NOT NULL LIMIT 5;

+--------------+---------------+------+------+--------+
|Manufacturer | Model         | Type | HP   | Thrust |
+--------------+---------------+------+------+--------+
|NONE         | NONE          |    0 |    0 |      0 |
|A.C.E.       | HIDR MARK III |    1 |   95 |      0 |
|A.C.E.       | UPRI MARK III |    1 |  100 |      0 |
|AEROMOMENT   | AM13 SERIES   |    8 |  100 |      0 |
|AEROMOMENT   | AM15 SERIES   |    8 |  117 |      0 |
+--------------+---------------+------+------+--------+
5 rows in set (0.00 sec)
– Engine Types by Count

mysql> SELECT CASE type WHEN ‘0’ THEN ‘None’ WHEN ‘1’ THEN ‘Reciprocating’ WHEN ‘2’ THEN ‘Turbo-prop’ WHEN ‘3’ THEN ‘Turbo-shaft’ WHEN ‘4’ THEN ‘Turbo-jet’ WHEN ‘5’ THEN ‘Turbo-fan’ WHEN ‘6’ THEN ‘Ramjet’ WHEN ‘7’ THEN ‘2 Cycle’ WHEN ‘8’ THEN ‘4 Cycle’ WHEN ‘9’ THEN ‘Unknown’ WHEN ‘10’ THEN ‘Electric’ WHEN ‘11’ THEN ‘Rotary’ ELSE CONCAT(‘Type’, type) END AS ‘Engine_Type’, COUNT(*) AS ‘Count’ FROM engines WHERE type IS NOT NULL GROUP BY type ORDER BY Count DESC;

+---------------+-------+
|Engine_Type   | Count |
+---------------+-------+
|Reciprocating |  2398 |
|Turbo-prop    |   749 |
|Turbo-fan     |   712 |
|Turbo-shaft   |   397 |
|Turbo-jet     |   191 |
|4 Cycle       |   167 |
|2 Cycle       |    70 |
|Electric      |    37 |
|Rotary        |     4 |
|None          |     1 |
|Unknown       |     1 |
+---------------+-------+
11 rows in set (0.00 sec)
– Engine details for the matched aircraft

Description: Engine manufacturer/model, type code, horsepower/thrust for the engine code seen on the matched aircraft.

mysql> SELECT er.code, er.mfr, er.model, er.type, er.horsepower, er.thrust FROM engines er WHERE er.code = ‘13120’;

+-------+----------+---------------+------+------------+--------+
|code  | mfr      | model         | type | horsepower | thrust |
+-------+----------+---------------+------+------------+--------+
|13120 | CFM INTL | LEAP-1B28 SER |    5 |          0 |  29317 |
+-------+----------+---------------+------+------------+--------+
1 row in set (0.00 sec)
– Find engines by manufacturer

mysql> SELECT * FROM engines WHERE mfr LIKE ‘%GE%’ ORDER BY horsepower DESC LIMIT 10;

+------+-------+------+--------------+------+------------+--------+
|id   | code  | mfr  | model        | type | horsepower | thrust |
+------+-------+------+--------------+------+------------+--------+
|1397 | 30040 | GE   | YF-120       |    5 |       5000 |      0 |
|1536 | 30179 | GE   | T64-GE-419   |    3 |       4750 |      0 |
|1517 | 30160 | GE   | T64-GE-416   |    3 |       4380 |      0 |
|1604 | 31132 | GE   | J-79-15A     |    4 |       4000 |      0 |
|1516 | 30159 | GE   | T64-GE-413   |    3 |       3925 |      0 |
|1376 | 30019 | GE   | CT64-820-4   |    2 |       3133 |      0 |
|1369 | 30012 | GE   | T64-GE-10    |    3 |       2850 |      0 |
|1363 | 30006 | GE   | CJ610-SER    |    4 |       2700 |      0 |
|1540 | 30183 | GE   | CT7-8A7      |    3 |       2685 |      0 |
|1547 | 30190 | GE   | YT706-GE-700 |    3 |       2638 |      0 |
+------+-------+------+--------------+------+------------+--------+
10 rows in set (0.01 sec)
–Top 10 manufacturers by engine count

mysql> SELECT mfr, COUNT(*) as engine_count FROM engines GROUP BY mfr ORDER BY engine_count DESC LIMIT 10;

+------------+--------------+
|mfr        | engine_count |
+------------+--------------+
|LYCOMING   |          868 |
|CONT MOTOR |          408 |
|P & W      |          352 |
|ROLLS-ROYC |          300 |
|WRIGHT     |          282 |
|GE         |          216 |
|P&W CANADA |          203 |
|HONEYWELL  |          197 |
|ALLIEDSIGN |          153 |
|GARRETT    |          120 |
+------------+--------------+
10 rows in set (0.00 sec)
– High horsepower engines

SELECT mfr, model, horsepower FROM engines WHERE horsepower > 1000 ORDER BY horsepower DESC LIMIT 20;

+------------+---------------+------------+
|mfr        | model         | horsepower |
+------------+---------------+------------+
|ROLLS      | RB3043/PRL700 |      18250 |
|ROLLS-ROYC | FLYGMTR RM6C  |      17500 |
|ROLLS-ROYC | TRENT 800     |      14500 |
|ROLL-ROYC  | TAY 620-15    |      13850 |
|ROLLS-ROYC | MK511-14      |      11400 |
|ROLLS-ROYC | SPEY 555-15P  |       9900 |
|P&W        | T34 SERIES    |       7500 |
|AVRO       | ALF 507-1F    |       7500 |
|LYCOMING   | ALF-502 SER.  |       7500 |
|HONEYWELL  | ALF 502 SER   |       7500 |
|LYCOMING   | AL503 SER     |       7500 |
|KLIMOV     | VK-1A         |       5950 |
|ROLLS-ROYC | TYNE 515      |       5521 |
|ALLIEDSIGN | ATF3-6        |       5440 |
|HONEYWELL  | ATF3-6        |       5440 |
|GARRETT    | ATF3-6        |       5440 |
|HONEYWELL  | ATF3-6A       |       5440 |
|GARRETT    | ATF3-6A       |       5440 |
|ALLIEDSIGN | ATF3-6A       |       5440 |
|ROLLS-ROYC | TYNE 512      |       5344 |
+------------+---------------+------------+
20 rows in set (0.00 sec)

– Jet engines (turbo-jet and turbo-fan) SELECT mfr, model, type, thrust FROM engines WHERE type IN (4, 5) ORDER BY thrust DESC LIMIT 20;

+------------+---------------+------+--------+
|mfr        | model         | type | thrust |
+------------+---------------+------+--------+
|GE         | GE90-115B     |    5 | 115540 |
|GE         | GE90-113B     |    5 | 113530 |
|GE         | GE90-110B1    |    5 | 110760 |
|GE         | GE9X SERIES   |    5 | 105000 |
|P & W      | PW4098        |    5 |  99040 |
|GE         | GE90-94B      |    5 |  97300 |
|GE         | GE90-90B      |    5 |  94000 |
|ROLLS-ROYC | RB211 895-17  |    5 |  92940 |
|P & W      | PW4090D       |    5 |  91790 |
|P & W      | PW4090        |    5 |  91790 |
|P & W      | PW4090-3      |    5 |  91790 |
|ROLLS-ROYC | RB211-892-17  |    5 |  91450 |
|ROLLS-ROYC | RB211 892B-17 |    5 |  91450 |
|ROLLS-ROY  | TRENT 892-17  |    5 |  91450 |
|ROLLS-ROYC | TRENT-892     |    5 |  91450 |
|GE         | GE90-85B      |    5 |  88870 |
|P & W      | PW4084        |    5 |  86760 |
|P & W      | PW4084D       |    5 |  86760 |
|ROLLS-ROYC | RB211 884-17  |    5 |  85430 |
|ROLLS-ROYC | RB211 884B-17 |    5 |  85430 |
+------------+---------------+------+--------+
20 rows in set (0.01 sec)

5. dealers table

Sample queries

– Top 5 Dealer Records

mysql> SELECT name AS ‘Dealer_Name’, city AS ‘City’, state_abbrev AS ‘State’, certificate_number AS ‘Cert_Number’ FROM dealers WHERE name IS NOT NULL LIMIT 5;

+---------------------------+------------------+-------+-------------+
|Dealer_Name               | City             | State | Cert_Number |
+---------------------------+------------------+-------+-------------+
|002050721TION LLC         | NULL             | NULL  | DCN3011     |
|007 ARKNASAS AVIATION LLC | NULL             | NULL  | DCN0566     |
|007 AVIATION GROUP LLC    | PORT SAINT LUCIE | FL    | D006431     |
|007 DUSTING INC           | LA JUNTA         | CO    | D005490     |
|1 FLIGHT UP LLC           | VACAVILLE        | CA    | 01-0463     |
+---------------------------+------------------+-------+-------------+
5 rows in set (0.00 sec)

6. Complex Joins

Sample queries

– Aircraft with Manufacturer Information

mysql> SELECT am.n_number AS ‘N-Number’, am.name AS ‘Owner’, am.city AS ‘City’, am.state AS ‘State’, ar.mfr AS ‘Manufacturer’, ar.model AS ‘Model’, am.year_mfr AS ‘Year’ FROM aircraft_master am LEFT JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE am.n_number IS NOT NULL LIMIT 5;

+----------+------------------------------+------------+-------+--------------------+--------------+------+
|N-Number | Owner                        | City       | State | Manufacturer       | Model        | Year |
+----------+------------------------------+------------+-------+--------------------+--------------+------+
|100      | BENE MARY D                  | KETCHUM    | OK    | PIPER              | J3C-65       | 1940 |
|10000    | 9AT LLC                      | NASHVILLE  | TN    | CIRRUS DESIGN CORP | SR22T        | NULL |
|10001    | STOOS ROBERT A               | LAKELAND   | FL    | WACO               | ASO          | 1928 |
|10004    | ETOS AIR LLC                 | NEW LONDON | TX    | CESSNA             | T182T        | NULL |
|10006    | COUTCHES ROBERT HERCULES DBA | LIVERMORE  | CA    | BEECH              | D-45 (T-34B) | 1955 |
+----------+------------------------------+------------+-------+--------------------+--------------+------+
5 rows in set (0.00 sec)
– Monthly delivery counts (Boeing + Airbus only) — past five years

Description: Counts aircraft with valid registrations per month, limited to Boeing or Airbus, for dates since 2020-01-01. Uses cert_issue_date as YYYYMMDD and formats month as YYYY-MM.

mysql> SELECT CONCAT(SUBSTRING(am.cert_issue_date,1,4), ‘-’, SUBSTRING(am.cert_issue_date,5,2)) AS cert_month, COUNT(*) AS aircraft_count FROM aircraft_master am JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE am.status_code = ‘V’ AND (ar.mfr = ‘BOEING’ OR ar.mfr LIKE ‘%AIRBUS%’) AND am.cert_issue_date IS NOT NULL AND am.cert_issue_date != ’’ AND am.cert_issue_date >= ‘20200101’ GROUP BY CONCAT(SUBSTRING(am.cert_issue_date,1,4), ‘-’, SUBSTRING(am.cert_issue_date,5,2)) ORDER BY cert_month DESC;

+------------+----------------+
|cert_month | aircraft_count |
+------------+----------------+
|2025-09    |             35 |
|2025-08    |             61 |
|2025-07    |             61 |
|2025-06    |             74 |
|2025-05    |             88 |
|2025-04    |            102 |
|2025-03    |             77 |
|2025-02    |             67 |
|2025-01    |             75 |
|2024-12    |            111 |
|2024-11    |             67 |
|2024-10    |             59 |
|2024-09    |             59 |
|2024-08    |             61 |
|2024-07    |             84 |
|2024-06    |             54 |
|2024-05    |             80 |
|2024-04    |             58 |
|2024-03    |             62 |
|2024-02    |             75 |
|2024-01    |             78 |
|2023-12    |            127 |
|2023-11    |             75 |
|2023-10    |             72 |
|2023-09    |             58 |
|2023-08    |             74 |
|2023-07    |             78 |
|2023-06    |             78 |
|2023-05    |            101 |
|2023-04    |             55 |
|2023-03    |            112 |
|2023-02    |             73 |
|2023-01    |             99 |
|2022-12    |            131 |
|2022-11    |             55 |
|2022-10    |             67 |
|2022-09    |             71 |
|2022-08    |             65 |
|2022-07    |             37 |
|2022-06    |             50 |
|2022-05    |             47 |
|2022-04    |             56 |
|2022-03    |             78 |
|2022-02    |             38 |
|2022-01    |             42 |
|2021-12    |             51 |
|2021-11    |             38 |
|2021-10    |             51 |
|2021-09    |             59 |
|2021-08    |             66 |
|2021-07    |             53 |
|2021-06    |             42 |
|2021-05    |             56 |
|2021-04    |             70 |
|2021-03    |             83 |
|2021-02    |             57 |
|2021-01    |             53 |
|2020-12    |             98 |
|2020-11    |             38 |
|2020-10    |             47 |
|2020-09    |             42 |
|2020-08    |             43 |
|2020-07    |             40 |
|2020-06    |             59 |
|2020-05    |             47 |
|2020-04    |             37 |
|2020-03    |             30 |
|2020-02    |             37 |
|2020-01    |             38 |
+------------+----------------+
69 rows in set (0.49 sec)
– Monthly delivery counts (Total, Boeing, Airbus, Others) — past five years

Description: Produces side-by-side columns for total, Boeing, Airbus, and Others, grouped by certification month since 2020-01-01.

mysql> SELECT CONCAT(SUBSTRING(am.cert_issue_date,1,4), ‘-’, SUBSTRING(am.cert_issue_date,5,2)) AS cert_month, COUNT(*) AS total, SUM(CASE WHEN ar.mfr = ‘BOEING’ THEN 1 ELSE 0 END) AS boeing, SUM(CASE WHEN ar.mfr LIKE ‘%AIRBUS%’ THEN 1 ELSE 0 END) AS airbus, SUM(CASE WHEN ar.mfr != ‘BOEING’ AND ar.mfr NOT LIKE ‘%AIRBUS%’ THEN 1 ELSE 0 END) AS others FROM aircraft_master am JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE am.status_code = ‘V’ AND am.cert_issue_date IS NOT NULL AND am.cert_issue_date != ’’ AND am.cert_issue_date >= ‘20200101’ GROUP BY CONCAT(SUBSTRING(am.cert_issue_date,1,4), ‘-’, SUBSTRING(am.cert_issue_date,5,2)) ORDER BY cert_month DESC;

+------------+-------+--------+--------+--------+
|cert_month | total | boeing | airbus | others |
+------------+-------+--------+--------+--------+
|2025-09    |  1030 |     18 |     17 |    995 |
|2025-08    |  3204 |     39 |     22 |   3143 |
|2025-07    |  3103 |     26 |     35 |   3042 |
|2025-06    |  2992 |     48 |     26 |   2918 |
|2025-05    |  3009 |     44 |     44 |   2921 |
|2025-04    |  2986 |     50 |     52 |   2884 |
|2025-03    |  3790 |     46 |     31 |   3713 |
|2025-02    |  2427 |     31 |     36 |   2360 |
|2025-01    |  2689 |     39 |     36 |   2614 |
|2024-12    |  1936 |     73 |     38 |   1825 |
|2024-11    |  2533 |     19 |     48 |   2466 |
|2024-10    |  2878 |     17 |     42 |   2819 |
|2024-09    |  2422 |     31 |     28 |   2363 |
|2024-08    |  2771 |     37 |     24 |   2710 |
|2024-07    |  3021 |     52 |     32 |   2937 |
|2024-06    |  2790 |     29 |     25 |   2736 |
|2024-05    |  3277 |     52 |     28 |   3197 |
|2024-04    |  2723 |     34 |     24 |   2665 |
|2024-03    |  2513 |     30 |     32 |   2451 |
|2024-02    |  2245 |     46 |     29 |   2170 |
|2024-01    |  3094 |     29 |     49 |   3016 |
|2023-12    |  2757 |     60 |     67 |   2630 |
|2023-11    |  2401 |     37 |     38 |   2326 |
|2023-10    |  2549 |     36 |     36 |   2477 |
|2023-09    |  2637 |     36 |     22 |   2579 |
|2023-08    |  3078 |     48 |     26 |   3004 |
|2023-07    |  2374 |     46 |     32 |   2296 |
|2023-06    |  2934 |     56 |     22 |   2856 |
|2023-05    |  3560 |     63 |     38 |   3459 |
|2023-04    |  3092 |     35 |     20 |   3037 |
|2023-03    |  3922 |     61 |     51 |   3810 |
|2023-02    |  3672 |     41 |     32 |   3599 |
|2023-01    |  3497 |     79 |     20 |   3398 |
|2022-12    |  2630 |     96 |     35 |   2499 |
|2022-11    |  2027 |     36 |     19 |   1972 |
|2022-10    |  1995 |     43 |     24 |   1928 |
|2022-09    |  1859 |     42 |     29 |   1788 |
|2022-08    |  2335 |     43 |     22 |   2270 |
|2022-07    |  1563 |     25 |     12 |   1526 |
|2022-06    |  1212 |     32 |     18 |   1162 |
|2022-05    |  1616 |     31 |     16 |   1569 |
|2022-04    |  1460 |     27 |     29 |   1404 |
|2022-03    |  1917 |     49 |     29 |   1839 |
|2022-02    |  1460 |     26 |     12 |   1422 |
|2022-01    |  1812 |     21 |     21 |   1770 |
|2021-12    |  1528 |     28 |     23 |   1477 |
|2021-11    |  1582 |     23 |     15 |   1544 |
|2021-10    |  1646 |     37 |     14 |   1595 |
|2021-09    |  1829 |     28 |     31 |   1770 |
|2021-08    |  2120 |     48 |     18 |   2054 |
|2021-07    |  1839 |     35 |     18 |   1786 |
|2021-06    |  1775 |     28 |     14 |   1733 |
|2021-05    |  1929 |     34 |     22 |   1873 |
|2021-04    |  1961 |     42 |     28 |   1891 |
|2021-03    |  1960 |     47 |     36 |   1877 |
|2021-02    |  1833 |     26 |     31 |   1776 |
|2021-01    |  1686 |     27 |     26 |   1633 |
|2020-12    |  1529 |     52 |     46 |   1431 |
|2020-11    |  1422 |     15 |     23 |   1384 |
|2020-10    |  1400 |     20 |     27 |   1353 |
|2020-09    |  1319 |     25 |     17 |   1277 |
|2020-08    |  1788 |     22 |     21 |   1745 |
|2020-07    |  1406 |     16 |     24 |   1366 |
|2020-06    |  1297 |     37 |     22 |   1238 |
|2020-05    |  1188 |     22 |     25 |   1141 |
|2020-04    |  1472 |     20 |     17 |   1435 |
|2020-03    |  1264 |     17 |     13 |   1234 |
|2020-02    |  1129 |     23 |     14 |   1092 |
|2020-01    |  1673 |     28 |     10 |   1635 |
+------------+-------+--------+--------+--------+
69 rows in set (0.56 sec)
– Monthly delivery counts (Total, Boeing, Airbus, Others, Hybrid Lift) — past five years

Description: Same as (2), adding a column for Hybrid Lift aircraft (Type Aircraft = ‘H’). This version includes a LIMIT 20 as used above; remove LIMIT for full range.

mysql> SELECT CONCAT(SUBSTRING(am.cert_issue_date,1,4), ‘-’, SUBSTRING(am.cert_issue_date,5,2)) AS cert_month, COUNT(*) AS total, SUM(CASE WHEN ar.mfr = ‘BOEING’ THEN 1 ELSE 0 END) AS boeing, SUM(CASE WHEN ar.mfr LIKE ‘%AIRBUS%’ THEN 1 ELSE 0 END) AS airbus, SUM(CASE WHEN ar.mfr != ‘BOEING’ AND ar.mfr NOT LIKE ‘%AIRBUS%’ THEN 1 ELSE 0 END) AS others, SUM(CASE WHEN am.type_aircraft = ‘H’ THEN 1 ELSE 0 END) AS hybrid_lift FROM aircraft_master am JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE am.status_code = ‘V’ AND am.cert_issue_date IS NOT NULL AND am.cert_issue_date != ’’ AND am.cert_issue_date >= ‘20200101’ GROUP BY CONCAT(SUBSTRING(am.cert_issue_date,1,4), ‘-’, SUBSTRING(am.cert_issue_date,5,2)) ORDER BY cert_month DESC LIMIT 20;

+------------+-------+--------+--------+--------+-------------+
|cert_month | total | boeing | airbus | others | hybrid_lift |
+------------+-------+--------+--------+--------+-------------+
|2025-09    |  1030 |     18 |     17 |    995 |           2 |
|2025-08    |  3204 |     39 |     22 |   3143 |           4 |
|2025-07    |  3103 |     26 |     35 |   3042 |          18 |
|2025-06    |  2992 |     48 |     26 |   2918 |          13 |
|2025-05    |  3009 |     44 |     44 |   2921 |          15 |
|2025-04    |  2986 |     50 |     52 |   2884 |         371 |
|2025-03    |  3790 |     46 |     31 |   3713 |         212 |
|2025-02    |  2427 |     31 |     36 |   2360 |          10 |
|2025-01    |  2689 |     39 |     36 |   2614 |           3 |
|2024-12    |  1936 |     73 |     38 |   1825 |           0 |
|2024-11    |  2533 |     19 |     48 |   2466 |          50 |
|2024-10    |  2878 |     17 |     42 |   2819 |          13 |
|2024-09    |  2422 |     31 |     28 |   2363 |          86 |
|2024-08    |  2771 |     37 |     24 |   2710 |          21 |
|2024-07    |  3021 |     52 |     32 |   2937 |           1 |
|2024-06    |  2790 |     29 |     25 |   2736 |           0 |
|2024-05    |  3277 |     52 |     28 |   3197 |           7 |
|2024-04    |  2723 |     34 |     24 |   2665 |           1 |
|2024-03    |  2513 |     30 |     32 |   2451 |           5 |
|2024-02    |  2245 |     46 |     29 |   2170 |           6 |
+------------+-------+--------+--------+--------+-------------+
20 rows in set (0.57 sec)
– List recent Hybrid Lift aircraft (examples)

Description: Shows 10 most recent valid Hybrid Lift aircraft (Type Aircraft = ‘H’) with owner, make/model, serial, and formatted certification date.

mysql> SELECT am.n_number, am.name, ar.mfr, ar.model, am.year_mfr, am.serial_number, am.type_aircraft, CONCAT(SUBSTRING(am.cert_issue_date,1,4), ‘-’, SUBSTRING(am.cert_issue_date,5,2), ‘-’, SUBSTRING(am.cert_issue_date,7,2)) AS cert_date FROM aircraft_master am JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE am.type_aircraft = ‘H’ AND am.status_code = ‘V’ ORDER BY am.cert_issue_date DESC LIMIT 10;

+----------+-------------------------------------+------------------------------+-----------+----------+----------------------+---------------+------------+
|n_number | name                                | mfr                          | model     | year_mfr | serial_number        | type_aircraft | cert_date  |
+----------+-------------------------------------+------------------------------+-----------+----------+----------------------+---------------+------------+
|805HX    | HONDA RESEARCH INSTITUTE USA INC    | HONDA RESEARCH INSTITUTE USA | F1        |     NULL | 001                  | H             | 2025-09-06 |
|625RZ    | CLEAN CUT HARVESTING LLC            | DJI                          | AGRAS T50 |     NULL | 1581F6BUB235J001003G | H             | 2025-09-05 |
|2014M    | UNIVERSITY OF MARYLAND              | EDGE AUTONOMY                | PENGUIN-B |     NULL | PNB1030              | H             | 2025-08-26 |
|246DR    | DANS DRONES LLC                     | DJI                          | AGRAS T50 |     NULL | 1581F6BUB2492001P543 | H             | 2025-08-11 |
|399NW    | TERRAPLEX PACIFIC NORTHWEST LLC     | DJI                          | AGRAS T50 |     NULL | 1581F6BUB246C001QL5T | H             | 2025-08-06 |
|251GG    | G4 DRONES LLC                       | DJI                          | AGRAS T50 |     NULL | 1581F6BUB246H0010K6E | H             | 2025-08-01 |
|1856A    | UNIVERSITY OF MARYLAND UAS RESEARCH | EDGE AUTONOMY                | PENGUIN-B |     NULL | PNB1031              | H             | 2025-07-31 |
|902LU    | AEROSPACE ASSETS LLC                | DJI                          | AGRAS T50 |     NULL | 1581F6BUB23AG0013PJZ | H             | 2025-07-28 |
|695VX    | EDGE AUTONOMY SLO LLC               | EDGE AUTONOMY SLO LLC        | VXE30     |     NULL | 695                  | H             | 2025-07-27 |
|125CR    | CR AGWORKS LLC                      | DJI                          | AGRAS T50 |     NULL | 1581F6BUB245R001U5P2 | H             | 2025-07-25 |
+----------+-------------------------------------+------------------------------+-----------+----------+----------------------+---------------+------------+
10 rows in set (0.01 sec)
– Latest Boeing/Airbus deliveries for 2025 (with YYYY-MM-DD dates)

Description: Lists recent valid Boeing/Airbus aircraft certified in 2025 with cert and last action dates formatted as YYYY-MM-DD.

mysql> SELECT am.n_number, am.name, ar.model, CONCAT(SUBSTRING(am.cert_issue_date,1,4), ‘-’, SUBSTRING(am.cert_issue_date,5,2), ‘-’, SUBSTRING(am.cert_issue_date,7,2)) AS cert_date FROM aircraft_master am JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE am.status_code = ‘V’ AND (ar.mfr = ‘BOEING’ OR ar.mfr LIKE ‘%AIRBUS%’) AND am.year_mfr = ‘2025’ ORDER BY am.cert_issue_date DESC LIMIT 20;

+----------+-------------------------------------------+-------------+------------+
|n_number | name                                      | model       | cert_date  |
+----------+-------------------------------------------+-------------+------------+
|8966S    | SOUTHWEST AIRLINES CO                     | 737-8       | 2025-09-04 |
|17410    | WILMINGTON TRUST COMPANY TRUSTEE          | 737-9       | 2025-09-03 |
|17411    | WILMINGTON TRUST CO TRUSTEE               | 737-9       | 2025-09-03 |
|57409    | WILMINGTON TRUST CO TRUSTEE               | 737-9       | 2025-09-03 |
|847MF    | AMERICAN AIRLINES INC                     | 787-9       | 2025-09-03 |
|849AN    | AMERICAN AIRLINES INC                     | 787-9       | 2025-09-02 |
|8965Q    | SOUTHWEST AIRLINES CO                     | 737-8       | 2025-09-02 |
|311UN    | AMERICAN AIRLINES INC                     | 737-8       | 2025-08-28 |
|17408    | WILMINGTON TRUST COMPANY TRUSTEE          | 737-9       | 2025-08-27 |
|825NV    | ALLEGIANT AIR LLC                         | 737-8200    | 2025-08-27 |
|8964L    | SOUTHWEST AIRLINES CO                     | 737-8       | 2025-08-26 |
|17407    | WILMINGTON TRUST CO TRUSTEE               | 737-9       | 2025-08-25 |
|22995    | UNITED AIRLINES INC                       | 787-9       | 2025-08-25 |
|17406    | WILMINGTON TRUST CO TRUSTEE               | 737-9       | 2025-08-22 |
|3271J    | JETBLUE AIRWAYS CORP                      | BD-500-1A11 | 2025-08-22 |
|910UP    | UNITED PARCEL SERVICE CO                  | 767-300F    | 2025-08-22 |
|991DE    | TVPX AIRCRAFT SOLUTIONS INC OWNER TRUSTEE | AS350B3     | 2025-08-22 |
|54538    | UNITED AIRLINES INC                       | A321-271NX  | 2025-08-21 |
|222HN    | HEALTHNET AEROMEDICAL SERVICES INC        | EC135 P3    | 2025-08-20 |
|256BZ    | BREEZE AVIATION GROUP INC                 | BD-500-1A11 | 2025-08-20 |
+----------+-------------------------------------------+-------------+------------+
20 rows in set (0.08 sec)
– Neighboring Boeing 737-8 serials (context for production sequence)

Description: Shows nearby Boeing 737-8 aircraft by serial range with cert dates to infer production cadence.

mysql> SELECT am.n_number, am.name, ar.mfr, ar.model, am.year_mfr, am.serial_number, am.cert_issue_date FROM aircraft_master am JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE ar.mfr = 'BOEING' AND ar.model = '737-8' AND am.serial_number BETWEEN '42620' AND '42630' ORDER BY am.serial_number\G;
*************************** 1. row ***************************
       n_number: 8963Q
           name: SOUTHWEST AIRLINES CO
            mfr: BOEING
          model: 737-8
       year_mfr: 2025
  serial_number: 42622
cert_issue_date: 20250701
*************************** 2. row ***************************
       n_number: 8966S
           name: SOUTHWEST AIRLINES CO
            mfr: BOEING
          model: 737-8
       year_mfr: 2025
  serial_number: 42626
cert_issue_date: 20250904
2 rows in set (0.01 sec)
– Complete field value distributions (all tables, all key fields, top 12 values per field)

Description: Shows each key field from each table with the top 12 unique values and their occurrence counts in parentheses, consolidated into one comprehensive table.

mysql> SELECT 'aircraft_master' as table_name, 'n_number' as field_name, GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') as top_values FROM (SELECT n_number as value, COUNT(*) as cnt FROM aircraft_master WHERE n_number IS NOT NULL GROUP BY n_number ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_master', 'status_code', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT status_code as value, COUNT(*) as cnt FROM aircraft_master WHERE status_code IS NOT NULL GROUP BY status_code ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_master', 'state', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT state as value, COUNT(*) as cnt FROM aircraft_master WHERE state IS NOT NULL GROUP BY state ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_master', 'type_aircraft', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT type_aircraft as value, COUNT(*) as cnt FROM aircraft_master WHERE type_aircraft IS NOT NULL GROUP BY type_aircraft ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_master', 'type_engine', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT type_engine as value, COUNT(*) as cnt FROM aircraft_master WHERE type_engine IS NOT NULL GROUP BY type_engine ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_master', 'year_mfr', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT year_mfr as value, COUNT(*) as cnt FROM aircraft_master WHERE year_mfr IS NOT NULL AND year_mfr != '' GROUP BY year_mfr ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_master', 'country', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT country as value, COUNT(*) as cnt FROM aircraft_master WHERE country IS NOT NULL GROUP BY country ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_master', 'certification', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT certification as value, COUNT(*) as cnt FROM aircraft_master WHERE certification IS NOT NULL GROUP BY certification ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_reference', 'mfr', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT mfr as value, COUNT(*) as cnt FROM aircraft_reference WHERE mfr IS NOT NULL GROUP BY mfr ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_reference', 'type_acft', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT type_acft as value, COUNT(*) as cnt FROM aircraft_reference WHERE type_acft IS NOT NULL GROUP BY type_acft ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_reference', 'type_eng', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT type_eng as value, COUNT(*) as cnt FROM aircraft_reference WHERE type_eng IS NOT NULL GROUP BY type_eng ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_reference', 'ac_cat', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT ac_cat as value, COUNT(*) as cnt FROM aircraft_reference WHERE ac_cat IS NOT NULL GROUP BY ac_cat ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_reference', 'no_eng', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT no_eng as value, COUNT(*) as cnt FROM aircraft_reference WHERE no_eng IS NOT NULL GROUP BY no_eng ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'aircraft_reference', 'ac_weight', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT ac_weight as value, COUNT(*) as cnt FROM aircraft_reference WHERE ac_weight IS NOT NULL GROUP BY ac_weight ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'engines', 'mfr', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT mfr as value, COUNT(*) as cnt FROM engines WHERE mfr IS NOT NULL GROUP BY mfr ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'engines', 'type', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT type as value, COUNT(*) as cnt FROM engines WHERE type IS NOT NULL GROUP BY type ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'dealers', 'ownership', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT ownership as value, COUNT(*) as cnt FROM dealers WHERE ownership IS NOT NULL GROUP BY ownership ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'dealers', 'state_abbrev', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT state_abbrev as value, COUNT(*) as cnt FROM dealers WHERE state_abbrev IS NOT NULL GROUP BY state_abbrev ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'deregistered_aircraft', 'status_code', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT status_code as value, COUNT(*) as cnt FROM deregistered_aircraft WHERE status_code IS NOT NULL GROUP BY status_code ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'deregistered_aircraft', 'country_mail', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT country_mail as value, COUNT(*) as cnt FROM deregistered_aircraft WHERE country_mail IS NOT NULL GROUP BY country_mail ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'documentation_index', 'doc_type', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT doc_type as value, COUNT(*) as cnt FROM documentation_index WHERE doc_type IS NOT NULL GROUP BY doc_type ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'documentation_index', 'type_collateral', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT type_collateral as value, COUNT(*) as cnt FROM documentation_index WHERE type_collateral IS NOT NULL GROUP BY type_collateral ORDER BY cnt DESC LIMIT 12) t UNION ALL SELECT 'reserved_numbers', 'state', GROUP_CONCAT(CONCAT(value, ' (', cnt, ')') SEPARATOR ', ') FROM (SELECT state as value, COUNT(*) as cnt FROM reserved_numbers WHERE state IS NOT NULL GROUP BY state ORDER BY cnt DESC LIMIT 12) t\G;
*************************** 1. row ***************************
table_name: aircraft_master
field_name: n_number
top_values: 100 (1), 10000 (1), 10001 (1), 10004 (1), 10006 (1), 10007 (1), 10009 (1), 1000A (1), 1000E (1), 1000G (1), 1000H (1), 1000J (1)
*************************** 2. row ***************************
table_name: aircraft_master
field_name: status_code
top_values: V (301669), R (1511), M (1064), 7 (857), 2 (224), N (217), 17 (164), 10 (147), 9 (110), 19 (87), 3 (82), 18 (60)
*************************** 3. row ***************************
table_name: aircraft_master
field_name: state
top_values: TX (28614), CA (25123), FL (21217), DE (10962), WA (10103), AK (9076), GA (8597), UT (8468), AZ (8303), OH (8113), IL (7881), CO (7261)
*************************** 4. row ***************************
table_name: aircraft_master
field_name: type_aircraft
top_values: 4 (218584), 5 (48847), 6 (24588), 2 (5179), 1 (4842), 8 (1902), 7 (1046), H (969), 9 (376), 3 (49), O (21)
*************************** 5. row ***************************
table_name: aircraft_master
field_name: type_engine
top_values: 1 (208755), 5 (26602), 8 (21029), 2 (13894), 10 (11036), 3 (9574), 0 (9051), 7 (4864), 4 (1514), 11 (75), 9 (5), 6 (4)
*************************** 6. row ***************************
table_name: aircraft_master
field_name: year_mfr
top_values: 1946 (8613), 1978 (6864), 1979 (6466), 1977 (6432), 1976 (6350), 1966 (5744), 1975 (5317), 1968 (5012), 1974 (4893), 2007 (4764), 1973 (4752), 1967 (4745)
*************************** 7. row ***************************
table_name: aircraft_master
field_name: country
top_values: US (301955), GB (761), RQ (482), DE (331), AT (100), VI (94), GU (65), CA (47), MP (31), CH (17), MX (12), IE (11)
*************************** 8. row ***************************
table_name: aircraft_master
field_name: certification
top_values: 1N (97126), 1 (42164), 1NU (31742), 42 (29249), 1T (21661), 1U (16729), 1B (4098), 43 (3989), 48A (3659), 31 (3446), 9A (3401), 1NA (2766)
*************************** 9. row ***************************
table_name: aircraft_reference
field_name: mfr
top_values: BOEING (1541), CESSNA (419), BEECH (336), PIPER (261), DOUGLAS (240), LOCKHEED (221), SIKORSKY (197), BELL (161), DJI (159), DEHAVILLAND (151), NORTH AMERICAN (144), FAIRCHILD (143)
*************************** 10. row ***************************
table_name: aircraft_reference
field_name: type_acft
top_values: 4 (71031), 6 (9577), 5 (4732), 1 (2935), 2 (1843), 8 (1330), 7 (1011), 9 (483), 3 (94), H (77), O (12)
*************************** 11. row ***************************
table_name: aircraft_reference
field_name: type_eng
top_values: 1 (69797), 8 (6707), 7 (5543), 0 (3999), 10 (1737), 5 (1695), 2 (1374), 4 (1192), 3 (1022), 11 (35), 9 (17), 6 (7)
*************************** 12. row ***************************
table_name: aircraft_reference
field_name: ac_cat
top_values: 1 (89371), 3 (3503), 2 (251)
*************************** 13. row ***************************
table_name: aircraft_reference
field_name: no_eng
top_values: 1 (82698), 2 (4153), 0 (4006), 4 (1303), 8 (291), 6 (286), 3 (277), 5 (47), 12 (17), 10 (13), 9 (12), 16 (8)
*************************** 14. row ***************************
table_name: aircraft_reference
field_name: ac_weight
top_values: CLASS 1 (87967), CLASS 3 (2890), CLASS 4 (1456), CLASS 2 (812)
*************************** 15. row ***************************
table_name: engines
field_name: mfr
top_values: LYCOMING (868), CONT MOTOR (408), P & W (352), ROLLS-ROYC (300), WRIGHT (282), GE (216), P&W CANADA (203), HONEYWELL (197), ALLIEDSIGN (153), GARRETT (120), ALLISON (113), CFM INTL (103)
*************************** 16. row ***************************
table_name: engines
field_name: type
top_values: 1 (2398), 2 (749), 5 (712), 3 (397), 4 (191), 8 (167), 7 (70), 10 (37), 11 (4), 0 (1), 9 (1)
*************************** 17. row ***************************
table_name: dealers
field_name: ownership
top_values: 3 (4244), 7 (3606), 1 (2420), 0 (1663), 2 (150), 4 (96), 8 (13)
*************************** 18. row ***************************
table_name: dealers
field_name: state_abbrev
top_values: FL (2193), CA (1135), TX (598), CO (508), TN (414), AR (385), MO (301), DE (284), PA (222), MI (213), GA (210), NY (201)
*************************** 19. row ***************************
table_name: deregistered_aircraft
field_name: status_code
top_values: V (185793), 16 (43739), A (36939), 29 (28562), 18 (17702), 2 (11196), 22 (10269), 7 (8948), 17 (5772), M (4594), 10 (3524), 20 (3113)
*************************** 20. row ***************************
table_name: deregistered_aircraft
field_name: country_mail
top_values: US (231403), CA (1004), RQ (836), BE (756), GB (731), MX (335), DE (292), VI (209), AU (181), GU (156), BR (148), AR (109)
*************************** 21. row ***************************
table_name: documentation_index
field_name: doc_type
top_values: BOS (5058), S/A (2509), REL (1729), DIS (203), CRT (36), REP (5)
*************************** 22. row ***************************
table_name: documentation_index
field_name: type_collateral
top_values: 1 (6870), 2 (1920), 9 (531), 3 (191), 4 (26), 5 (2)
*************************** 23. row ***************************
table_name: reserved_numbers
field_name: state
top_values: DC (51257), FL (9052), OK (6444), TX (4327), CA (3613), WA (2266), OH (2056), TN (1507), KS (1484), VA (1377), GA (1327), AZ (1153)
23 rows in set (0.67 sec)
– Top 20 Boeing fixed-wing models by registration count

mysql> SELECT ar.model, COUNT(*) as registered_count, CASE WHEN ar.type_acft = ‘4’ THEN ‘Single Engine’ WHEN ar.type_acft = ‘5’ THEN ‘Multi Engine’ ELSE ‘Other’ END AS engine_type, CASE WHEN ar.model LIKE ‘737%’ THEN ‘737 Family’ WHEN ar.model LIKE ‘%STEARMAN%’ OR ar.model LIKE ‘PT-%’ OR ar.model LIKE ‘A75%’ OR ar.model LIKE ‘B75%’ OR ar.model LIKE ‘E75%’ OR ar.model LIKE ‘D75%’ THEN ‘Stearman Trainers’ WHEN ar.model LIKE ‘757%’ THEN ‘757 Family’ WHEN ar.model LIKE ‘767%’ THEN ‘767 Family’ WHEN ar.model LIKE ‘777%’ THEN ‘777 Family’ WHEN ar.model LIKE ‘787%’ THEN ‘787 Family’ WHEN ar.model LIKE ‘747%’ THEN ‘747 Family’ WHEN ar.model LIKE ‘717%’ THEN ‘717 Family’ WHEN ar.model REGEXP ‘1{1,2}[0-9]{1,2}$’ AND ar.model NOT REGEXP ‘^(737|747|757|767|777|787|717)’ THEN ‘Historical/Classic’ ELSE ‘Other Boeing’ END AS aircraft_family FROM aircraft_master am JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE ar.mfr = ‘BOEING’ AND ar.type_acft IN (‘4’, ‘5’) AND am.status_code = ‘V’ GROUP BY ar.model, ar.type_acft ORDER BY registered_count DESC LIMIT 20;

+-------------+------------------+---------------+-------------------+
|model       | registered_count | engine_type   | aircraft_family   |
+-------------+------------------+---------------+-------------------+
|A75N1(PT17) |              746 | Single Engine | Stearman Trainers |
|737-8       |              504 | Multi Engine  | 737 Family        |
|737-823     |              278 | Multi Engine  | 737 Family        |
|E75         |              255 | Single Engine | Stearman Trainers |
|737-7H4     |              253 | Multi Engine  | 737 Family        |
|B75N1       |              237 | Single Engine | Stearman Trainers |
|737-9       |              202 | Multi Engine  | 737 Family        |
|767-300F    |              142 | Multi Engine  | 767 Family        |
|737-824     |              135 | Multi Engine  | 737 Family        |
|737-800     |              132 | Multi Engine  | 737 Family        |
|737-924ER   |              130 | Multi Engine  | 737 Family        |
|737-8H4     |              125 | Multi Engine  | 737 Family        |
|717-200     |              115 | Multi Engine  | 717 Family        |
|737-900ER   |              101 | Multi Engine  | 737 Family        |
|A75         |               93 | Single Engine | Stearman Trainers |
|787-9       |               93 | Multi Engine  | 787 Family        |
|E75N1       |               79 | Single Engine | Stearman Trainers |
|757-24APF   |               75 | Multi Engine  | 757 Family        |
|787-8       |               74 | Multi Engine  | 787 Family        |
|737-832     |               73 | Multi Engine  | 737 Family        |
+-------------+------------------+---------------+-------------------+
20 rows in set (0.03 sec)
– Top 10 Single Engine Boeing models

SELECT ar.model, COUNT(*) as registered_count, CASE WHEN ar.model LIKE ‘737%’ THEN ‘737 Family’ WHEN ar.model LIKE ‘%STEARMAN%’ OR ar.model LIKE ‘PT-%’ OR ar.model LIKE ‘A75%’ OR ar.model LIKE ‘B75%’ OR ar.model LIKE ‘E75%’ OR ar.model LIKE ‘D75%’ THEN ‘Stearman Trainers’ WHEN ar.model LIKE ‘757%’ THEN ‘757 Family’ WHEN ar.model LIKE ‘767%’ THEN ‘767 Family’ WHEN ar.model LIKE ‘777%’ THEN ‘777 Family’ WHEN ar.model LIKE ‘787%’ THEN ‘787 Family’ WHEN ar.model LIKE ‘747%’ THEN ‘747 Family’ WHEN ar.model LIKE ‘717%’ THEN ‘717 Family’ WHEN ar.model REGEXP ‘2{1,2}[0-9]{1,2}$’ AND ar.model NOT REGEXP ‘^(737|747|757|767|777|787|717)’ THEN ‘Historical/Classic’ ELSE ‘Other Boeing’ END AS aircraft_family FROM aircraft_master am JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE ar.mfr = ‘BOEING’ AND ar.type_acft = ‘4’ AND am.status_code = ‘V’ GROUP BY ar.model ORDER BY registered_count DESC LIMIT 10;

+-------------+------------------+-------------------+
|model       | registered_count | aircraft_family   |
+-------------+------------------+-------------------+
|A75N1(PT17) |              746 | Stearman Trainers |
|E75         |              255 | Stearman Trainers |
|B75N1       |              237 | Stearman Trainers |
|A75         |               93 | Stearman Trainers |
|E75N1       |               79 | Stearman Trainers |
|A75N1       |               57 | Stearman Trainers |
|D75N1       |               35 | Stearman Trainers |
|PT-17       |               34 | Stearman Trainers |
|A75L300     |               33 | Stearman Trainers |
|A75L3       |               32 | Stearman Trainers |
+-------------+------------------+-------------------+
10 rows in set (0.02 sec)
– Top 10 Multi Engine Boeing models

SELECT ar.model, COUNT(*) as registered_count, CASE WHEN ar.model LIKE ‘737%’ THEN ‘737 Family’ WHEN ar.model LIKE ‘%STEARMAN%’ OR ar.model LIKE ‘PT-%’ OR ar.model LIKE ‘A75%’ OR ar.model LIKE ‘B75%’ OR ar.model LIKE ‘E75%’ OR ar.model LIKE ‘D75%’ THEN ‘Stearman Trainers’ WHEN ar.model LIKE ‘757%’ THEN ‘757 Family’ WHEN ar.model LIKE ‘767%’ THEN ‘767 Family’ WHEN ar.model LIKE ‘777%’ THEN ‘777 Family’ WHEN ar.model LIKE ‘787%’ THEN ‘787 Family’ WHEN ar.model LIKE ‘747%’ THEN ‘747 Family’ WHEN ar.model LIKE ‘717%’ THEN ‘717 Family’ WHEN ar.model REGEXP ‘3{1,2}[0-9]{1,2}$’ AND ar.model NOT REGEXP ‘^(737|747|757|767|777|787|717)’ THEN ‘Historical/Classic’ ELSE ‘Other Boeing’ END AS aircraft_family FROM aircraft_master am JOIN aircraft_reference ar ON am.mfr_mdl_code = ar.code WHERE ar.mfr = ‘BOEING’ AND ar.type_acft = ‘5’ AND am.status_code = ‘V’ GROUP BY ar.model ORDER BY registered_count DESC LIMIT 10;

+-----------+------------------+-----------------+
|model     | registered_count | aircraft_family |
+-----------+------------------+-----------------+
|737-8     |              504 | 737 Family      |
|737-823   |              278 | 737 Family      |
|737-7H4   |              253 | 737 Family      |
|737-9     |              202 | 737 Family      |
|767-300F  |              142 | 767 Family      |
|737-824   |              135 | 737 Family      |
|737-800   |              132 | 737 Family      |
|737-924ER |              130 | 737 Family      |
|737-8H4   |              125 | 737 Family      |
|717-200   |              115 | 717 Family      |
+-----------+------------------+-----------------+
10 rows in set (0.03 sec)

Key Insights & Conclusions

Executive Summary of Findings

This comprehensive analysis of the FAA aircraft registration database reveals significant insights into the US civil aviation landscape. The database contains 910,788 total records across 7 tables, representing one of the most complete datasets of aircraft registration information available.

Database Scale & Scope

Database Statistics

  • Active Aircraft: 302,049 currently registered aircraft
  • Historical Records: 359,778 deregistered aircraft
  • Reference Data: 93,503 aircraft specifications and 4,708 engine types
  • Total Storage: ~148.5 MB of structured data

Geographic Distribution Insights

The analysis reveals a highly concentrated aircraft registration pattern:

  • Texas dominates with 28,614 aircraft (9.47% of total)
  • Top 3 states (TX, CA, FL) account for nearly 25% of all registrations
  • Delaware’s high ranking (4th place) suggests significant corporate aircraft registrations
  • International presence includes 761 aircraft from Great Britain and 482 from other countries

Manufacturing Landscape

The aircraft manufacturing sector leaders are:

  • Boeing leads with 1,541 different aircraft models/types
  • General Aviation manufacturers (Cessna, Beech, Piper) maintain strong market presence
  • Helicopter sector is well-represented by Sikorsky and Bell
  • Emerging technology (DJI drones) is gaining database presence

Ideas for Further Analysis

  1. Geographic Analysis: Investigate Delaware’s ranking
  2. Manufacturing Trends: Analyze the impact of COVID-19 on aircraft manufacturing patterns
  3. International Fleet: Examine the international aircraft registrations
  4. Engine Analysis: Explore further the 4,708 engine specifications and their performance characteristics
  5. Deregistration Patterns: Analyze the 359,778 deregistered aircraft for industry insights

  1. A-Z↩︎

  2. A-Z↩︎

  3. A-Z↩︎