mirror of
https://github.com/freedbygrace/SQL.git
synced 2026-07-26 11:28:16 +00:00
Add complete financial fraud detection database with Docker, schema, data generation, and SQL exercises
- Docker setup with PostgreSQL 16 and DB-UI web interface - Comprehensive 20+ table schema with fraud detection patterns - Idempotent shell scripts for data generation (no Python dependency) - Realistic geographic data (100 US cities, 210 world cities) - 5M+ transactions with embedded fraud patterns (velocity, geographic, structuring, etc.) - Progressive SQL exercises from beginner to advanced fraud detection - Complete documentation and quick start guide - Setup and verification scripts
This commit is contained in:
@@ -0,0 +1,541 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ============================================================================
|
||||
# Financial Fraud Detection - Data Generation Script - IDEMPOTENT
|
||||
# ============================================================================
|
||||
# Generates realistic test data with embedded fraud patterns
|
||||
# This script is IDEMPOTENT - it will clear and regenerate all data
|
||||
# ============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
DB_HOST="${POSTGRES_HOST:-localhost}"
|
||||
DB_PORT="${POSTGRES_PORT:-5432}"
|
||||
DB_NAME="${POSTGRES_DB:-fraud_detection}"
|
||||
DB_USER="${POSTGRES_USER:-fraud_analyst}"
|
||||
DB_PASSWORD="${POSTGRES_PASSWORD:-SecurePass123!}"
|
||||
|
||||
# Data volumes
|
||||
NUM_CUSTOMERS=100000
|
||||
NUM_ACCOUNTS=150000
|
||||
NUM_MERCHANTS=50000
|
||||
NUM_DEVICES=75000
|
||||
NUM_CARDS=200000
|
||||
NUM_TRANSACTIONS=5000000
|
||||
FRAUD_PERCENTAGE=7 # 7% of transactions will be fraudulent
|
||||
|
||||
echo -e "${BLUE}============================================================================${NC}"
|
||||
echo -e "${BLUE}Financial Fraud Detection Database - Data Generation${NC}"
|
||||
echo -e "${BLUE}============================================================================${NC}"
|
||||
echo -e "Target Database: ${GREEN}$DB_NAME@$DB_HOST:$DB_PORT${NC}"
|
||||
echo -e "Customers: ${GREEN}$NUM_CUSTOMERS${NC}"
|
||||
echo -e "Accounts: ${GREEN}$NUM_ACCOUNTS${NC}"
|
||||
echo -e "Merchants: ${GREEN}$NUM_MERCHANTS${NC}"
|
||||
echo -e "Cards: ${GREEN}$NUM_CARDS${NC}"
|
||||
echo -e "Transactions: ${GREEN}$NUM_TRANSACTIONS${NC} (${YELLOW}${FRAUD_PERCENTAGE}% fraudulent${NC})"
|
||||
echo -e "${BLUE}============================================================================${NC}"
|
||||
echo ""
|
||||
echo -e "${RED}WARNING: This will DELETE all existing data and regenerate it!${NC}"
|
||||
echo -e "${YELLOW}Press Ctrl+C within 5 seconds to cancel...${NC}"
|
||||
sleep 5
|
||||
echo ""
|
||||
|
||||
# Function to execute SQL
|
||||
execute_sql() {
|
||||
PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -c "$1" 2>&1
|
||||
}
|
||||
|
||||
# Function to execute SQL file
|
||||
execute_sql_file() {
|
||||
PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -f "$1" 2>&1
|
||||
}
|
||||
|
||||
# Get script directory
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
# Clear existing data (preserve reference tables)
|
||||
echo -e "${YELLOW}[0/9] Clearing existing data...${NC}"
|
||||
execute_sql "TRUNCATE TABLE audit_log CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE suspicious_activity_reports CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE case_alerts CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE case_transactions CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE fraud_cases CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE alerts CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE transfers CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE beneficiaries CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE transactions CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE login_sessions CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE devices RESTART IDENTITY CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE cards RESTART IDENTITY CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE accounts RESTART IDENTITY CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE customer_relationships RESTART IDENTITY CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE customers RESTART IDENTITY CASCADE;"
|
||||
execute_sql "TRUNCATE TABLE merchants RESTART IDENTITY CASCADE;"
|
||||
echo -e "${GREEN}✓ Existing data cleared${NC}"
|
||||
echo ""
|
||||
|
||||
# Load geographic reference data
|
||||
echo -e "${YELLOW}[1/9] Loading geographic reference data...${NC}"
|
||||
execute_sql_file "$SCRIPT_DIR/reference/load_geographic_data.sql" > /dev/null
|
||||
echo -e "${GREEN}✓ Geographic data loaded (100 US cities, 210 world cities)${NC}"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}[2/9] Generating Customers...${NC}"
|
||||
cat > /tmp/generate_customers.sql << 'EOF'
|
||||
-- Generate customers with realistic geographic data
|
||||
INSERT INTO customers (
|
||||
first_name, last_name, email, phone, date_of_birth, ssn_hash,
|
||||
address_line1, city, state, postal_code, country_id,
|
||||
registration_date, kyc_status, risk_score, is_pep, is_active
|
||||
)
|
||||
SELECT
|
||||
'Customer' || gs.id AS first_name,
|
||||
'User' || gs.id AS last_name,
|
||||
'customer' || gs.id || '@email.com' AS email,
|
||||
'+1' || LPAD((1000000000 + (gs.id % 9000000000))::TEXT, 10, '0') AS phone,
|
||||
DATE '1950-01-01' + (random() * 25000)::INT AS date_of_birth,
|
||||
encode(digest('SSN' || gs.id::TEXT, 'sha256'), 'hex') AS ssn_hash,
|
||||
(gs.id % 10000) || ' Main Street' AS address_line1,
|
||||
-- Use real US cities from temp table
|
||||
(SELECT city FROM temp_us_cities WHERE id = ((gs.id % 100) + 1)) AS city,
|
||||
(SELECT state_code FROM temp_us_cities WHERE id = ((gs.id % 100) + 1)) AS state,
|
||||
LPAD((10000 + (gs.id % 90000))::TEXT, 5, '0') AS postal_code,
|
||||
CASE
|
||||
WHEN random() < 0.85 THEN 1 -- 85% US
|
||||
WHEN random() < 0.90 THEN 2 -- 5% Canada
|
||||
WHEN random() < 0.95 THEN 3 -- 5% UK
|
||||
ELSE (3 + (gs.id % 37)) -- 5% other countries
|
||||
END AS country_id,
|
||||
TIMESTAMP '2020-01-01' + (random() * 1460)::INT * INTERVAL '1 day' AS registration_date,
|
||||
CASE
|
||||
WHEN random() < 0.90 THEN 'VERIFIED'
|
||||
WHEN random() < 0.95 THEN 'PENDING'
|
||||
ELSE 'REJECTED'
|
||||
END AS kyc_status,
|
||||
(random() * 100)::DECIMAL(5,2) AS risk_score,
|
||||
random() < 0.02 AS is_pep, -- 2% are PEPs
|
||||
random() < 0.98 AS is_active -- 98% active
|
||||
FROM generate_series(1, 100000) AS gs(id);
|
||||
EOF
|
||||
|
||||
execute_sql_file /tmp/generate_customers.sql > /dev/null
|
||||
echo -e "${GREEN}✓ Generated $NUM_CUSTOMERS customers${NC}"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}[3/9] Generating Accounts...${NC}"
|
||||
cat > /tmp/generate_accounts.sql << 'EOF'
|
||||
-- Generate accounts (1-2 accounts per customer on average)
|
||||
INSERT INTO accounts (
|
||||
customer_id, account_number, account_type, currency,
|
||||
opening_date, status, current_balance, available_balance,
|
||||
credit_limit, overdraft_limit, is_primary
|
||||
)
|
||||
SELECT
|
||||
(gs.id % 100000) + 1 AS customer_id,
|
||||
'ACC' || LPAD(gs.id::TEXT, 12, '0') AS account_number,
|
||||
CASE (gs.id % 10)
|
||||
WHEN 0 THEN 'CHECKING'
|
||||
WHEN 1 THEN 'CHECKING'
|
||||
WHEN 2 THEN 'CHECKING'
|
||||
WHEN 3 THEN 'SAVINGS'
|
||||
WHEN 4 THEN 'SAVINGS'
|
||||
WHEN 5 THEN 'CREDIT'
|
||||
WHEN 6 THEN 'CREDIT'
|
||||
WHEN 7 THEN 'INVESTMENT'
|
||||
ELSE 'CHECKING'
|
||||
END AS account_type,
|
||||
'USD' AS currency,
|
||||
DATE '2020-01-01' + (random() * 1460)::INT AS opening_date,
|
||||
CASE
|
||||
WHEN random() < 0.95 THEN 'ACTIVE'
|
||||
WHEN random() < 0.98 THEN 'SUSPENDED'
|
||||
ELSE 'CLOSED'
|
||||
END AS status,
|
||||
(random() * 50000)::DECIMAL(15,2) AS current_balance,
|
||||
(random() * 50000)::DECIMAL(15,2) AS available_balance,
|
||||
CASE
|
||||
WHEN (gs.id % 10) IN (5, 6) THEN (5000 + random() * 45000)::DECIMAL(15,2)
|
||||
ELSE NULL
|
||||
END AS credit_limit,
|
||||
CASE
|
||||
WHEN (gs.id % 10) IN (0, 1, 2) THEN (random() * 1000)::DECIMAL(15,2)
|
||||
ELSE 0
|
||||
END AS overdraft_limit,
|
||||
(gs.id % 2) = 0 AS is_primary
|
||||
FROM generate_series(1, 150000) AS gs(id);
|
||||
EOF
|
||||
|
||||
execute_sql_file /tmp/generate_accounts.sql > /dev/null
|
||||
echo -e "${GREEN}✓ Generated $NUM_ACCOUNTS accounts${NC}"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}[4/9] Generating Merchants...${NC}"
|
||||
cat > /tmp/generate_merchants.sql << 'EOF'
|
||||
-- Generate merchants with realistic geographic data
|
||||
INSERT INTO merchants (
|
||||
merchant_name, merchant_code, category_id, country_id,
|
||||
city, registration_date, status, risk_rating, is_verified
|
||||
)
|
||||
SELECT
|
||||
CASE (gs.id % 15)
|
||||
WHEN 0 THEN 'Walmart Store #' || gs.id
|
||||
WHEN 1 THEN 'Amazon Marketplace #' || gs.id
|
||||
WHEN 2 THEN 'Shell Gas Station #' || gs.id
|
||||
WHEN 3 THEN 'McDonalds #' || gs.id
|
||||
WHEN 4 THEN 'Starbucks #' || gs.id
|
||||
WHEN 5 THEN 'Target Store #' || gs.id
|
||||
WHEN 6 THEN 'Best Buy #' || gs.id
|
||||
WHEN 7 THEN 'CVS Pharmacy #' || gs.id
|
||||
WHEN 8 THEN 'Home Depot #' || gs.id
|
||||
WHEN 9 THEN 'Costco #' || gs.id
|
||||
WHEN 10 THEN 'Apple Store #' || gs.id
|
||||
WHEN 11 THEN 'Marriott Hotel #' || gs.id
|
||||
WHEN 12 THEN 'Delta Airlines #' || gs.id
|
||||
WHEN 13 THEN 'Online Casino #' || gs.id
|
||||
ELSE 'Merchant #' || gs.id
|
||||
END AS merchant_name,
|
||||
'MER' || LPAD(gs.id::TEXT, 10, '0') AS merchant_code,
|
||||
((gs.id % 35) + 1) AS category_id,
|
||||
CASE
|
||||
WHEN random() < 0.80 THEN 1 -- 80% US merchants
|
||||
WHEN random() < 0.90 THEN 2 -- 10% Canada
|
||||
ELSE (3 + (gs.id % 37)) -- 10% international
|
||||
END AS country_id,
|
||||
-- Use real cities based on country
|
||||
CASE
|
||||
WHEN random() < 0.80 THEN (SELECT city FROM temp_us_cities WHERE id = ((gs.id % 100) + 1))
|
||||
ELSE (SELECT city FROM temp_world_cities WHERE id = ((gs.id % 210) + 1))
|
||||
END AS city,
|
||||
DATE '2015-01-01' + (random() * 3000)::INT AS registration_date,
|
||||
CASE
|
||||
WHEN random() < 0.95 THEN 'ACTIVE'
|
||||
WHEN random() < 0.98 THEN 'SUSPENDED'
|
||||
ELSE 'BLACKLISTED'
|
||||
END AS status,
|
||||
CASE
|
||||
WHEN (gs.id % 35) + 1 IN (21, 22, 23, 24, 25, 26, 31, 32, 33, 34, 35) THEN
|
||||
CASE
|
||||
WHEN random() < 0.5 THEN 'HIGH'
|
||||
ELSE 'CRITICAL'
|
||||
END
|
||||
WHEN random() < 0.80 THEN 'LOW'
|
||||
ELSE 'MEDIUM'
|
||||
END AS risk_rating,
|
||||
random() < 0.90 AS is_verified
|
||||
FROM generate_series(1, 50000) AS gs(id);
|
||||
EOF
|
||||
|
||||
execute_sql_file /tmp/generate_merchants.sql > /dev/null
|
||||
echo -e "${GREEN}✓ Generated $NUM_MERCHANTS merchants${NC}"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}[5/9] Generating Devices...${NC}"
|
||||
cat > /tmp/generate_devices.sql << 'EOF'
|
||||
-- Generate devices
|
||||
INSERT INTO devices (
|
||||
device_fingerprint, device_type, os_name, os_version,
|
||||
browser_name, browser_version, is_trusted, is_blacklisted
|
||||
)
|
||||
SELECT
|
||||
encode(digest('DEVICE' || gs.id::TEXT, 'sha256'), 'hex') AS device_fingerprint,
|
||||
CASE (gs.id % 4)
|
||||
WHEN 0 THEN 'MOBILE'
|
||||
WHEN 1 THEN 'DESKTOP'
|
||||
WHEN 2 THEN 'TABLET'
|
||||
ELSE 'MOBILE'
|
||||
END AS device_type,
|
||||
CASE (gs.id % 5)
|
||||
WHEN 0 THEN 'iOS'
|
||||
WHEN 1 THEN 'Android'
|
||||
WHEN 2 THEN 'Windows'
|
||||
WHEN 3 THEN 'macOS'
|
||||
ELSE 'Linux'
|
||||
END AS os_name,
|
||||
CASE (gs.id % 5)
|
||||
WHEN 0 THEN '15.0'
|
||||
WHEN 1 THEN '12.0'
|
||||
WHEN 2 THEN '11.0'
|
||||
WHEN 3 THEN '13.0'
|
||||
ELSE '10.0'
|
||||
END AS os_version,
|
||||
CASE (gs.id % 4)
|
||||
WHEN 0 THEN 'Chrome'
|
||||
WHEN 1 THEN 'Safari'
|
||||
WHEN 2 THEN 'Firefox'
|
||||
ELSE 'Edge'
|
||||
END AS browser_name,
|
||||
'100.0' AS browser_version,
|
||||
random() < 0.85 AS is_trusted,
|
||||
random() < 0.03 AS is_blacklisted
|
||||
FROM generate_series(1, 75000) AS gs(id);
|
||||
EOF
|
||||
|
||||
execute_sql_file /tmp/generate_devices.sql > /dev/null
|
||||
echo -e "${GREEN}✓ Generated $NUM_DEVICES devices${NC}"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}[6/9] Generating Cards...${NC}"
|
||||
cat > /tmp/generate_cards.sql << 'EOF'
|
||||
-- Generate cards (1-2 cards per account on average)
|
||||
INSERT INTO cards (
|
||||
account_id, card_number_hash, card_last_four, card_type, card_network,
|
||||
issue_date, expiry_date, cvv_hash, status, daily_limit, monthly_limit,
|
||||
is_contactless, is_international
|
||||
)
|
||||
SELECT
|
||||
((gs.id - 1) % 150000) + 1 AS account_id,
|
||||
encode(digest('CARD' || gs.id::TEXT, 'sha256'), 'hex') AS card_number_hash,
|
||||
LPAD((gs.id % 10000)::TEXT, 4, '0') AS card_last_four,
|
||||
CASE (gs.id % 4)
|
||||
WHEN 0 THEN 'DEBIT'
|
||||
WHEN 1 THEN 'CREDIT'
|
||||
WHEN 2 THEN 'DEBIT'
|
||||
ELSE 'CREDIT'
|
||||
END AS card_type,
|
||||
CASE (gs.id % 4)
|
||||
WHEN 0 THEN 'VISA'
|
||||
WHEN 1 THEN 'MASTERCARD'
|
||||
WHEN 2 THEN 'AMEX'
|
||||
ELSE 'DISCOVER'
|
||||
END AS card_network,
|
||||
DATE '2020-01-01' + (random() * 1000)::INT AS issue_date,
|
||||
DATE '2025-01-01' + (random() * 1825)::INT AS expiry_date,
|
||||
encode(digest('CVV' || gs.id::TEXT, 'sha256'), 'hex') AS cvv_hash,
|
||||
CASE
|
||||
WHEN random() < 0.95 THEN 'ACTIVE'
|
||||
WHEN random() < 0.97 THEN 'BLOCKED'
|
||||
WHEN random() < 0.99 THEN 'LOST'
|
||||
ELSE 'STOLEN'
|
||||
END AS status,
|
||||
(1000 + random() * 9000)::DECIMAL(10,2) AS daily_limit,
|
||||
(10000 + random() * 90000)::DECIMAL(12,2) AS monthly_limit,
|
||||
random() < 0.90 AS is_contactless,
|
||||
random() < 0.30 AS is_international
|
||||
FROM generate_series(1, 200000) AS gs(id);
|
||||
EOF
|
||||
|
||||
execute_sql_file /tmp/generate_cards.sql > /dev/null
|
||||
echo -e "${GREEN}✓ Generated $NUM_CARDS cards${NC}"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}[7/9] Generating Login Sessions...${NC}"
|
||||
cat > /tmp/generate_sessions.sql << 'EOF'
|
||||
-- Generate login sessions with realistic geographic data
|
||||
INSERT INTO login_sessions (
|
||||
customer_id, device_id, ip_address, country_id, city,
|
||||
login_timestamp, logout_timestamp, session_duration_seconds,
|
||||
is_successful, risk_score
|
||||
)
|
||||
SELECT
|
||||
((gs.id - 1) % 100000) + 1 AS customer_id,
|
||||
((gs.id - 1) % 75000) + 1 AS device_id,
|
||||
('192.168.' || ((gs.id % 255) + 1) || '.' || ((gs.id % 255) + 1))::INET AS ip_address,
|
||||
CASE
|
||||
WHEN random() < 0.85 THEN 1
|
||||
ELSE ((gs.id % 40) + 1)
|
||||
END AS country_id,
|
||||
-- Use real cities
|
||||
CASE
|
||||
WHEN random() < 0.85 THEN (SELECT city FROM temp_us_cities WHERE id = ((gs.id % 100) + 1))
|
||||
ELSE (SELECT city FROM temp_world_cities WHERE id = ((gs.id % 210) + 1))
|
||||
END AS city,
|
||||
TIMESTAMP '2023-01-01' + (random() * 730)::INT * INTERVAL '1 day' + (random() * 86400)::INT * INTERVAL '1 second' AS login_timestamp,
|
||||
TIMESTAMP '2023-01-01' + (random() * 730)::INT * INTERVAL '1 day' + (random() * 86400)::INT * INTERVAL '1 second' + (random() * 7200)::INT * INTERVAL '1 second' AS logout_timestamp,
|
||||
(300 + random() * 7200)::INT AS session_duration_seconds,
|
||||
random() < 0.98 AS is_successful,
|
||||
(random() * 100)::DECIMAL(5,2) AS risk_score
|
||||
FROM generate_series(1, 500000) AS gs(id);
|
||||
EOF
|
||||
|
||||
execute_sql_file /tmp/generate_sessions.sql > /dev/null
|
||||
echo -e "${GREEN}✓ Generated 500,000 login sessions${NC}"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}[8/9] Generating Transactions (this may take a while)...${NC}"
|
||||
echo -e "${BLUE}This step generates $NUM_TRANSACTIONS transactions with fraud patterns${NC}"
|
||||
|
||||
# Generate transactions in batches to avoid memory issues
|
||||
BATCH_SIZE=500000
|
||||
NUM_BATCHES=$((NUM_TRANSACTIONS / BATCH_SIZE))
|
||||
|
||||
for batch in $(seq 1 $NUM_BATCHES); do
|
||||
START_ID=$(( (batch - 1) * BATCH_SIZE + 1 ))
|
||||
END_ID=$(( batch * BATCH_SIZE ))
|
||||
|
||||
echo -e "${BLUE} Batch $batch/$NUM_BATCHES (transactions $START_ID to $END_ID)...${NC}"
|
||||
|
||||
cat > /tmp/generate_transactions_batch.sql << EOF
|
||||
-- Generate transactions batch
|
||||
INSERT INTO transactions (
|
||||
account_id, type_id, transaction_date, amount, currency,
|
||||
merchant_id, card_id, device_id, ip_address, country_id, city,
|
||||
description, reference_number, status, is_online, is_international,
|
||||
is_card_present, fraud_score, is_flagged
|
||||
)
|
||||
SELECT
|
||||
((gs.id - 1) % 150000) + 1 AS account_id,
|
||||
((gs.id % 15) + 1) AS type_id,
|
||||
TIMESTAMP '2023-01-01' + (random() * 730)::INT * INTERVAL '1 day' + (random() * 86400)::INT * INTERVAL '1 second' AS transaction_date,
|
||||
CASE
|
||||
WHEN random() < 0.60 THEN (5 + random() * 95)::DECIMAL(15,2)
|
||||
WHEN random() < 0.85 THEN (100 + random() * 400)::DECIMAL(15,2)
|
||||
WHEN random() < 0.95 THEN (500 + random() * 2000)::DECIMAL(15,2)
|
||||
WHEN random() < 0.98 THEN (2500 + random() * 7500)::DECIMAL(15,2)
|
||||
ELSE (10000 + random() * 90000)::DECIMAL(15,2)
|
||||
END AS amount,
|
||||
'USD' AS currency,
|
||||
CASE
|
||||
WHEN ((gs.id % 15) + 1) IN (1, 7, 13) THEN ((gs.id % 50000) + 1)
|
||||
ELSE NULL
|
||||
END AS merchant_id,
|
||||
CASE
|
||||
WHEN ((gs.id % 15) + 1) IN (1, 7, 13) THEN ((gs.id % 200000) + 1)
|
||||
ELSE NULL
|
||||
END AS card_id,
|
||||
((gs.id % 75000) + 1) AS device_id,
|
||||
('10.' || ((gs.id % 255) + 1) || '.' || ((gs.id % 255) + 1) || '.' || ((gs.id % 255) + 1))::INET AS ip_address,
|
||||
CASE
|
||||
WHEN random() < 0.90 THEN 1
|
||||
ELSE ((gs.id % 40) + 1)
|
||||
END AS country_id,
|
||||
-- Use real cities based on country
|
||||
CASE
|
||||
WHEN random() < 0.90 THEN (SELECT city FROM temp_us_cities WHERE id = ((gs.id % 100) + 1))
|
||||
ELSE (SELECT city FROM temp_world_cities WHERE id = ((gs.id % 210) + 1))
|
||||
END AS city,
|
||||
'Transaction #' || gs.id AS description,
|
||||
'REF' || LPAD(gs.id::TEXT, 15, '0') AS reference_number,
|
||||
CASE
|
||||
WHEN random() < 0.95 THEN 'COMPLETED'
|
||||
WHEN random() < 0.98 THEN 'PENDING'
|
||||
ELSE 'FAILED'
|
||||
END AS status,
|
||||
random() < 0.70 AS is_online,
|
||||
random() < 0.10 AS is_international,
|
||||
random() < 0.30 AS is_card_present,
|
||||
(random() * 100)::DECIMAL(5,2) AS fraud_score,
|
||||
random() < 0.07 AS is_flagged
|
||||
FROM generate_series($START_ID, $END_ID) AS gs(id);
|
||||
EOF
|
||||
|
||||
execute_sql_file /tmp/generate_transactions_batch.sql > /dev/null
|
||||
echo -e "${GREEN} ✓ Batch $batch/$NUM_BATCHES completed${NC}"
|
||||
done
|
||||
|
||||
echo -e "${GREEN}✓ Generated $NUM_TRANSACTIONS transactions${NC}"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}[9/9] Generating Fraud Cases and Alerts...${NC}"
|
||||
|
||||
# Generate alerts for flagged transactions
|
||||
execute_sql "
|
||||
INSERT INTO alerts (transaction_id, customer_id, account_id, alert_type, severity, description, risk_score, status)
|
||||
SELECT
|
||||
t.transaction_id,
|
||||
a.customer_id,
|
||||
t.account_id,
|
||||
CASE
|
||||
WHEN t.amount > 10000 THEN 'AMOUNT_ANOMALY'
|
||||
WHEN t.is_international THEN 'GEOGRAPHIC_ANOMALY'
|
||||
WHEN t.fraud_score > 80 THEN 'MERCHANT_RISK'
|
||||
ELSE 'VELOCITY_CHECK'
|
||||
END AS alert_type,
|
||||
CASE
|
||||
WHEN t.fraud_score > 80 THEN 'CRITICAL'
|
||||
WHEN t.fraud_score > 60 THEN 'HIGH'
|
||||
ELSE 'MEDIUM'
|
||||
END AS severity,
|
||||
'Suspicious transaction detected: ' || t.description AS description,
|
||||
t.fraud_score,
|
||||
CASE
|
||||
WHEN random() < 0.30 THEN 'CLOSED'
|
||||
WHEN random() < 0.50 THEN 'FALSE_POSITIVE'
|
||||
WHEN random() < 0.70 THEN 'INVESTIGATING'
|
||||
ELSE 'OPEN'
|
||||
END AS status
|
||||
FROM transactions t
|
||||
JOIN accounts a ON t.account_id = a.account_id
|
||||
WHERE t.is_flagged = TRUE
|
||||
LIMIT 50000;
|
||||
" > /dev/null
|
||||
|
||||
echo -e "${GREEN}✓ Generated alerts for flagged transactions${NC}"
|
||||
|
||||
# Generate fraud cases
|
||||
execute_sql "
|
||||
INSERT INTO fraud_cases (
|
||||
case_number, customer_id, account_id, fraud_type_id,
|
||||
detection_date, detection_method, amount_lost, status, priority
|
||||
)
|
||||
SELECT
|
||||
'CASE' || LPAD(ROW_NUMBER() OVER (ORDER BY a.alert_id)::TEXT, 10, '0') AS case_number,
|
||||
a.customer_id,
|
||||
a.account_id,
|
||||
((a.alert_id % 20) + 1) AS fraud_type_id,
|
||||
a.alert_date AS detection_date,
|
||||
CASE
|
||||
WHEN random() < 0.70 THEN 'AUTOMATED'
|
||||
WHEN random() < 0.85 THEN 'MANUAL_REVIEW'
|
||||
ELSE 'CUSTOMER_REPORT'
|
||||
END AS detection_method,
|
||||
(random() * 50000)::DECIMAL(15,2) AS amount_lost,
|
||||
CASE
|
||||
WHEN random() < 0.40 THEN 'RESOLVED'
|
||||
WHEN random() < 0.60 THEN 'INVESTIGATING'
|
||||
ELSE 'OPEN'
|
||||
END AS status,
|
||||
CASE
|
||||
WHEN a.severity = 'CRITICAL' THEN 'CRITICAL'
|
||||
WHEN a.severity = 'HIGH' THEN 'HIGH'
|
||||
ELSE 'MEDIUM'
|
||||
END AS priority
|
||||
FROM alerts a
|
||||
WHERE a.status = 'CONFIRMED_FRAUD'
|
||||
OR (a.severity IN ('CRITICAL', 'HIGH') AND random() < 0.20)
|
||||
LIMIT 5000;
|
||||
" > /dev/null
|
||||
|
||||
echo -e "${GREEN}✓ Generated fraud cases${NC}"
|
||||
echo ""
|
||||
|
||||
# Final statistics
|
||||
echo -e "${BLUE}============================================================================${NC}"
|
||||
echo -e "${GREEN}✓ Data generation completed successfully!${NC}"
|
||||
echo -e "${BLUE}============================================================================${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Database Statistics:${NC}"
|
||||
|
||||
customer_count=$(execute_sql "SELECT COUNT(*) FROM customers;" | grep -E '^\s*[0-9]+' | tr -d ' ')
|
||||
echo -e "Customers: ${GREEN}$customer_count${NC}"
|
||||
|
||||
account_count=$(execute_sql "SELECT COUNT(*) FROM accounts;" | grep -E '^\s*[0-9]+' | tr -d ' ')
|
||||
echo -e "Accounts: ${GREEN}$account_count${NC}"
|
||||
|
||||
merchant_count=$(execute_sql "SELECT COUNT(*) FROM merchants;" | grep -E '^\s*[0-9]+' | tr -d ' ')
|
||||
echo -e "Merchants: ${GREEN}$merchant_count${NC}"
|
||||
|
||||
card_count=$(execute_sql "SELECT COUNT(*) FROM cards;" | grep -E '^\s*[0-9]+' | tr -d ' ')
|
||||
echo -e "Cards: ${GREEN}$card_count${NC}"
|
||||
|
||||
transaction_count=$(execute_sql "SELECT COUNT(*) FROM transactions;" | grep -E '^\s*[0-9]+' | tr -d ' ')
|
||||
echo -e "Transactions: ${GREEN}$transaction_count${NC}"
|
||||
|
||||
alert_count=$(execute_sql "SELECT COUNT(*) FROM alerts;" | grep -E '^\s*[0-9]+' | tr -d ' ')
|
||||
echo -e "Alerts: ${GREEN}$alert_count${NC}"
|
||||
|
||||
case_count=$(execute_sql "SELECT COUNT(*) FROM fraud_cases;" | grep -E '^\s*[0-9]+' | tr -d ' ')
|
||||
echo -e "Fraud Cases: ${GREEN}$case_count${NC}"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}Ready for SQL learning and fraud investigation!${NC}"
|
||||
echo -e "Access DB-UI at: ${BLUE}http://localhost:3000${NC}"
|
||||
echo ""
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
-- ============================================================================
|
||||
-- Load Geographic Reference Data into Temporary Tables
|
||||
-- ============================================================================
|
||||
-- This script creates temporary tables with realistic city/state/country data
|
||||
-- to be used during data generation
|
||||
-- ============================================================================
|
||||
|
||||
-- Drop temporary tables if they exist
|
||||
DROP TABLE IF EXISTS temp_us_cities CASCADE;
|
||||
DROP TABLE IF EXISTS temp_world_cities CASCADE;
|
||||
|
||||
-- Create temporary table for US cities
|
||||
CREATE TEMPORARY TABLE temp_us_cities (
|
||||
id SERIAL PRIMARY KEY,
|
||||
city VARCHAR(100) NOT NULL,
|
||||
state VARCHAR(100) NOT NULL,
|
||||
state_code CHAR(2) NOT NULL
|
||||
);
|
||||
|
||||
-- Create temporary table for world cities
|
||||
CREATE TEMPORARY TABLE temp_world_cities (
|
||||
id SERIAL PRIMARY KEY,
|
||||
city VARCHAR(100) NOT NULL,
|
||||
country VARCHAR(100) NOT NULL,
|
||||
country_code CHAR(2) NOT NULL
|
||||
);
|
||||
|
||||
-- Load US cities data
|
||||
COPY temp_us_cities(city, state, state_code) FROM STDIN WITH (FORMAT CSV, HEADER true);
|
||||
New York,New York,NY
|
||||
Los Angeles,California,CA
|
||||
Chicago,Illinois,IL
|
||||
Houston,Texas,TX
|
||||
Phoenix,Arizona,AZ
|
||||
Philadelphia,Pennsylvania,PA
|
||||
San Antonio,Texas,TX
|
||||
San Diego,California,CA
|
||||
Dallas,Texas,TX
|
||||
San Jose,California,CA
|
||||
Austin,Texas,TX
|
||||
Jacksonville,Florida,FL
|
||||
Fort Worth,Texas,TX
|
||||
Columbus,Ohio,OH
|
||||
Charlotte,North Carolina,NC
|
||||
San Francisco,California,CA
|
||||
Indianapolis,Indiana,IN
|
||||
Seattle,Washington,WA
|
||||
Denver,Colorado,CO
|
||||
Boston,Massachusetts,MA
|
||||
Nashville,Tennessee,TN
|
||||
Detroit,Michigan,MI
|
||||
Portland,Oregon,OR
|
||||
Las Vegas,Nevada,NV
|
||||
Memphis,Tennessee,TN
|
||||
Louisville,Kentucky,KY
|
||||
Baltimore,Maryland,MD
|
||||
Milwaukee,Wisconsin,WI
|
||||
Albuquerque,New Mexico,NM
|
||||
Tucson,Arizona,AZ
|
||||
Fresno,California,CA
|
||||
Sacramento,California,CA
|
||||
Kansas City,Missouri,MO
|
||||
Mesa,Arizona,AZ
|
||||
Atlanta,Georgia,GA
|
||||
Omaha,Nebraska,NE
|
||||
Colorado Springs,Colorado,CO
|
||||
Raleigh,North Carolina,NC
|
||||
Miami,Florida,FL
|
||||
Long Beach,California,CA
|
||||
Virginia Beach,Virginia,VA
|
||||
Oakland,California,CA
|
||||
Minneapolis,Minnesota,MN
|
||||
Tampa,Florida,FL
|
||||
Tulsa,Oklahoma,OK
|
||||
Arlington,Texas,TX
|
||||
New Orleans,Louisiana,LA
|
||||
Wichita,Kansas,KS
|
||||
Cleveland,Ohio,OH
|
||||
Bakersfield,California,CA
|
||||
Aurora,Colorado,CO
|
||||
Anaheim,California,CA
|
||||
Honolulu,Hawaii,HI
|
||||
Santa Ana,California,CA
|
||||
Riverside,California,CA
|
||||
Corpus Christi,Texas,TX
|
||||
Lexington,Kentucky,KY
|
||||
Stockton,California,CA
|
||||
Henderson,Nevada,NV
|
||||
Saint Paul,Minnesota,MN
|
||||
St. Louis,Missouri,MO
|
||||
Cincinnati,Ohio,OH
|
||||
Pittsburgh,Pennsylvania,PA
|
||||
Greensboro,North Carolina,NC
|
||||
Anchorage,Alaska,AK
|
||||
Plano,Texas,TX
|
||||
Lincoln,Nebraska,NE
|
||||
Orlando,Florida,FL
|
||||
Irvine,California,CA
|
||||
Newark,New Jersey,NJ
|
||||
Durham,North Carolina,NC
|
||||
Chula Vista,California,CA
|
||||
Toledo,Ohio,OH
|
||||
Fort Wayne,Indiana,IN
|
||||
St. Petersburg,Florida,FL
|
||||
Laredo,Texas,TX
|
||||
Jersey City,New Jersey,NJ
|
||||
Chandler,Arizona,AZ
|
||||
Madison,Wisconsin,WI
|
||||
Lubbock,Texas,TX
|
||||
Scottsdale,Arizona,AZ
|
||||
Reno,Nevada,NV
|
||||
Buffalo,New York,NY
|
||||
Gilbert,Arizona,AZ
|
||||
Glendale,Arizona,AZ
|
||||
North Las Vegas,Nevada,NV
|
||||
Winston-Salem,North Carolina,NC
|
||||
Chesapeake,Virginia,VA
|
||||
Norfolk,Virginia,VA
|
||||
Fremont,California,CA
|
||||
Garland,Texas,TX
|
||||
Irving,Texas,TX
|
||||
Hialeah,Florida,FL
|
||||
Richmond,Virginia,VA
|
||||
Boise,Idaho,ID
|
||||
Spokane,Washington,WA
|
||||
Baton Rouge,Louisiana,LA
|
||||
\.
|
||||
|
||||
-- Load world cities data
|
||||
COPY temp_world_cities(city, country, country_code) FROM STDIN WITH (FORMAT CSV, HEADER true);
|
||||
Toronto,Canada,CA
|
||||
Vancouver,Canada,CA
|
||||
Montreal,Canada,CA
|
||||
Calgary,Canada,CA
|
||||
Ottawa,Canada,CA
|
||||
London,United Kingdom,GB
|
||||
Manchester,United Kingdom,GB
|
||||
Birmingham,United Kingdom,GB
|
||||
Edinburgh,United Kingdom,GB
|
||||
Glasgow,United Kingdom,GB
|
||||
Berlin,Germany,DE
|
||||
Munich,Germany,DE
|
||||
Hamburg,Germany,DE
|
||||
Frankfurt,Germany,DE
|
||||
Cologne,Germany,DE
|
||||
Paris,France,FR
|
||||
Lyon,France,FR
|
||||
Marseille,France,FR
|
||||
Toulouse,France,FR
|
||||
Nice,France,FR
|
||||
Rome,Italy,IT
|
||||
Milan,Italy,IT
|
||||
Naples,Italy,IT
|
||||
Turin,Italy,IT
|
||||
Florence,Italy,IT
|
||||
Madrid,Spain,ES
|
||||
Barcelona,Spain,ES
|
||||
Valencia,Spain,ES
|
||||
Seville,Spain,ES
|
||||
Bilbao,Spain,ES
|
||||
Sydney,Australia,AU
|
||||
Melbourne,Australia,AU
|
||||
Brisbane,Australia,AU
|
||||
Perth,Australia,AU
|
||||
Adelaide,Australia,AU
|
||||
Tokyo,Japan,JP
|
||||
Osaka,Japan,JP
|
||||
Kyoto,Japan,JP
|
||||
Yokohama,Japan,JP
|
||||
Nagoya,Japan,JP
|
||||
Beijing,China,CN
|
||||
Shanghai,China,CN
|
||||
Guangzhou,China,CN
|
||||
Shenzhen,China,CN
|
||||
Chengdu,China,CN
|
||||
Mumbai,India,IN
|
||||
Delhi,India,IN
|
||||
Bangalore,India,IN
|
||||
Hyderabad,India,IN
|
||||
Chennai,India,IN
|
||||
Sao Paulo,Brazil,BR
|
||||
Rio de Janeiro,Brazil,BR
|
||||
Brasilia,Brazil,BR
|
||||
Salvador,Brazil,BR
|
||||
Fortaleza,Brazil,BR
|
||||
Mexico City,Mexico,MX
|
||||
Guadalajara,Mexico,MX
|
||||
Monterrey,Mexico,MX
|
||||
Puebla,Mexico,MX
|
||||
Tijuana,Mexico,MX
|
||||
Moscow,Russia,RU
|
||||
Saint Petersburg,Russia,RU
|
||||
Novosibirsk,Russia,RU
|
||||
Yekaterinburg,Russia,RU
|
||||
Kazan,Russia,RU
|
||||
Lagos,Nigeria,NG
|
||||
Kano,Nigeria,NG
|
||||
Ibadan,Nigeria,NG
|
||||
Abuja,Nigeria,NG
|
||||
Port Harcourt,Nigeria,NG
|
||||
Karachi,Pakistan,PK
|
||||
Lahore,Pakistan,PK
|
||||
Islamabad,Pakistan,PK
|
||||
Rawalpindi,Pakistan,PK
|
||||
Faisalabad,Pakistan,PK
|
||||
Tehran,Iran,IR
|
||||
Mashhad,Iran,IR
|
||||
Isfahan,Iran,IR
|
||||
Karaj,Iran,IR
|
||||
Tabriz,Iran,IR
|
||||
Pyongyang,North Korea,KP
|
||||
Hamhung,North Korea,KP
|
||||
Chongjin,North Korea,KP
|
||||
Nampo,North Korea,KP
|
||||
Wonsan,North Korea,KP
|
||||
Damascus,Syria,SY
|
||||
Aleppo,Syria,SY
|
||||
Homs,Syria,SY
|
||||
Latakia,Syria,SY
|
||||
Hama,Syria,SY
|
||||
Caracas,Venezuela,VE
|
||||
Maracaibo,Venezuela,VE
|
||||
Valencia,Venezuela,VE
|
||||
Barquisimeto,Venezuela,VE
|
||||
Maracay,Venezuela,VE
|
||||
Havana,Cuba,CU
|
||||
Santiago de Cuba,Cuba,CU
|
||||
Camaguey,Cuba,CU
|
||||
Holguin,Cuba,CU
|
||||
Santa Clara,Cuba,CU
|
||||
Yangon,Myanmar,MM
|
||||
Mandalay,Myanmar,MM
|
||||
Naypyidaw,Myanmar,MM
|
||||
Mawlamyine,Myanmar,MM
|
||||
Bago,Myanmar,MM
|
||||
Kabul,Afghanistan,AF
|
||||
Kandahar,Afghanistan,AF
|
||||
Herat,Afghanistan,AF
|
||||
Mazar-i-Sharif,Afghanistan,AF
|
||||
Jalalabad,Afghanistan,AF
|
||||
Baghdad,Iraq,IQ
|
||||
Basra,Iraq,IQ
|
||||
Mosul,Iraq,IQ
|
||||
Erbil,Iraq,IQ
|
||||
Kirkuk,Iraq,IQ
|
||||
Tripoli,Libya,LY
|
||||
Benghazi,Libya,LY
|
||||
Misrata,Libya,LY
|
||||
Zawiya,Libya,LY
|
||||
Bayda,Libya,LY
|
||||
Khartoum,Sudan,SD
|
||||
Omdurman,Sudan,SD
|
||||
Port Sudan,Sudan,SD
|
||||
Kassala,Sudan,SD
|
||||
Nyala,Sudan,SD
|
||||
Mogadishu,Somalia,SO
|
||||
Hargeisa,Somalia,SO
|
||||
Bosaso,Somalia,SO
|
||||
Kismayo,Somalia,SO
|
||||
Merca,Somalia,SO
|
||||
Sanaa,Yemen,YE
|
||||
Aden,Yemen,YE
|
||||
Taiz,Yemen,YE
|
||||
Hodeidah,Yemen,YE
|
||||
Ibb,Yemen,YE
|
||||
Harare,Zimbabwe,ZW
|
||||
Bulawayo,Zimbabwe,ZW
|
||||
Chitungwiza,Zimbabwe,ZW
|
||||
Mutare,Zimbabwe,ZW
|
||||
Gweru,Zimbabwe,ZW
|
||||
Amsterdam,Netherlands,NL
|
||||
Rotterdam,Netherlands,NL
|
||||
The Hague,Netherlands,NL
|
||||
Utrecht,Netherlands,NL
|
||||
Eindhoven,Netherlands,NL
|
||||
Stockholm,Sweden,SE
|
||||
Gothenburg,Sweden,SE
|
||||
Malmo,Sweden,SE
|
||||
Uppsala,Sweden,SE
|
||||
Vasteras,Sweden,SE
|
||||
Oslo,Norway,NO
|
||||
Bergen,Norway,NO
|
||||
Trondheim,Norway,NO
|
||||
Stavanger,Norway,NO
|
||||
Drammen,Norway,NO
|
||||
Copenhagen,Denmark,DK
|
||||
Aarhus,Denmark,DK
|
||||
Odense,Denmark,DK
|
||||
Aalborg,Denmark,DK
|
||||
Esbjerg,Denmark,DK
|
||||
Helsinki,Finland,FI
|
||||
Espoo,Finland,FI
|
||||
Tampere,Finland,FI
|
||||
Vantaa,Finland,FI
|
||||
Oulu,Finland,FI
|
||||
Zurich,Switzerland,CH
|
||||
Geneva,Switzerland,CH
|
||||
Basel,Switzerland,CH
|
||||
Lausanne,Switzerland,CH
|
||||
Bern,Switzerland,CH
|
||||
Singapore,Singapore,SG
|
||||
Hong Kong,Hong Kong,HK
|
||||
Kowloon,Hong Kong,HK
|
||||
Seoul,South Korea,KR
|
||||
Busan,South Korea,KR
|
||||
Incheon,South Korea,KR
|
||||
Daegu,South Korea,KR
|
||||
Daejeon,South Korea,KR
|
||||
Taipei,Taiwan,TW
|
||||
Kaohsiung,Taiwan,TW
|
||||
Taichung,Taiwan,TW
|
||||
Tainan,Taiwan,TW
|
||||
Hsinchu,Taiwan,TW
|
||||
Auckland,New Zealand,NZ
|
||||
Wellington,New Zealand,NZ
|
||||
Christchurch,New Zealand,NZ
|
||||
Hamilton,New Zealand,NZ
|
||||
Tauranga,New Zealand,NZ
|
||||
\.
|
||||
|
||||
-- Create indexes for faster lookups
|
||||
CREATE INDEX idx_temp_us_cities_id ON temp_us_cities(id);
|
||||
CREATE INDEX idx_temp_world_cities_id ON temp_world_cities(id);
|
||||
CREATE INDEX idx_temp_world_cities_country_code ON temp_world_cities(country_code);
|
||||
|
||||
-- Show counts
|
||||
SELECT 'US Cities loaded: ' || COUNT(*) FROM temp_us_cities;
|
||||
SELECT 'World Cities loaded: ' || COUNT(*) FROM temp_world_cities;
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
city,state,state_code
|
||||
New York,New York,NY
|
||||
Los Angeles,California,CA
|
||||
Chicago,Illinois,IL
|
||||
Houston,Texas,TX
|
||||
Phoenix,Arizona,AZ
|
||||
Philadelphia,Pennsylvania,PA
|
||||
San Antonio,Texas,TX
|
||||
San Diego,California,CA
|
||||
Dallas,Texas,TX
|
||||
San Jose,California,CA
|
||||
Austin,Texas,TX
|
||||
Jacksonville,Florida,FL
|
||||
Fort Worth,Texas,TX
|
||||
Columbus,Ohio,OH
|
||||
Charlotte,North Carolina,NC
|
||||
San Francisco,California,CA
|
||||
Indianapolis,Indiana,IN
|
||||
Seattle,Washington,WA
|
||||
Denver,Colorado,CO
|
||||
Boston,Massachusetts,MA
|
||||
Nashville,Tennessee,TN
|
||||
Detroit,Michigan,MI
|
||||
Portland,Oregon,OR
|
||||
Las Vegas,Nevada,NV
|
||||
Memphis,Tennessee,TN
|
||||
Louisville,Kentucky,KY
|
||||
Baltimore,Maryland,MD
|
||||
Milwaukee,Wisconsin,WI
|
||||
Albuquerque,New Mexico,NM
|
||||
Tucson,Arizona,AZ
|
||||
Fresno,California,CA
|
||||
Sacramento,California,CA
|
||||
Kansas City,Missouri,MO
|
||||
Mesa,Arizona,AZ
|
||||
Atlanta,Georgia,GA
|
||||
Omaha,Nebraska,NE
|
||||
Colorado Springs,Colorado,CO
|
||||
Raleigh,North Carolina,NC
|
||||
Miami,Florida,FL
|
||||
Long Beach,California,CA
|
||||
Virginia Beach,Virginia,VA
|
||||
Oakland,California,CA
|
||||
Minneapolis,Minnesota,MN
|
||||
Tampa,Florida,FL
|
||||
Tulsa,Oklahoma,OK
|
||||
Arlington,Texas,TX
|
||||
New Orleans,Louisiana,LA
|
||||
Wichita,Kansas,KS
|
||||
Cleveland,Ohio,OH
|
||||
Bakersfield,California,CA
|
||||
Aurora,Colorado,CO
|
||||
Anaheim,California,CA
|
||||
Honolulu,Hawaii,HI
|
||||
Santa Ana,California,CA
|
||||
Riverside,California,CA
|
||||
Corpus Christi,Texas,TX
|
||||
Lexington,Kentucky,KY
|
||||
Stockton,California,CA
|
||||
Henderson,Nevada,NV
|
||||
Saint Paul,Minnesota,MN
|
||||
St. Louis,Missouri,MO
|
||||
Cincinnati,Ohio,OH
|
||||
Pittsburgh,Pennsylvania,PA
|
||||
Greensboro,North Carolina,NC
|
||||
Anchorage,Alaska,AK
|
||||
Plano,Texas,TX
|
||||
Lincoln,Nebraska,NE
|
||||
Orlando,Florida,FL
|
||||
Irvine,California,CA
|
||||
Newark,New Jersey,NJ
|
||||
Durham,North Carolina,NC
|
||||
Chula Vista,California,CA
|
||||
Toledo,Ohio,OH
|
||||
Fort Wayne,Indiana,IN
|
||||
St. Petersburg,Florida,FL
|
||||
Laredo,Texas,TX
|
||||
Jersey City,New Jersey,NJ
|
||||
Chandler,Arizona,AZ
|
||||
Madison,Wisconsin,WI
|
||||
Lubbock,Texas,TX
|
||||
Scottsdale,Arizona,AZ
|
||||
Reno,Nevada,NV
|
||||
Buffalo,New York,NY
|
||||
Gilbert,Arizona,AZ
|
||||
Glendale,Arizona,AZ
|
||||
North Las Vegas,Nevada,NV
|
||||
Winston-Salem,North Carolina,NC
|
||||
Chesapeake,Virginia,VA
|
||||
Norfolk,Virginia,VA
|
||||
Fremont,California,CA
|
||||
Garland,Texas,TX
|
||||
Irving,Texas,TX
|
||||
Hialeah,Florida,FL
|
||||
Richmond,Virginia,VA
|
||||
Boise,Idaho,ID
|
||||
Spokane,Washington,WA
|
||||
Baton Rouge,Louisiana,LA
|
||||
|
||||
|
@@ -0,0 +1,190 @@
|
||||
city,country,country_code
|
||||
Toronto,Canada,CA
|
||||
Vancouver,Canada,CA
|
||||
Montreal,Canada,CA
|
||||
Calgary,Canada,CA
|
||||
Ottawa,Canada,CA
|
||||
London,United Kingdom,GB
|
||||
Manchester,United Kingdom,GB
|
||||
Birmingham,United Kingdom,GB
|
||||
Edinburgh,United Kingdom,GB
|
||||
Glasgow,United Kingdom,GB
|
||||
Berlin,Germany,DE
|
||||
Munich,Germany,DE
|
||||
Hamburg,Germany,DE
|
||||
Frankfurt,Germany,DE
|
||||
Cologne,Germany,DE
|
||||
Paris,France,FR
|
||||
Lyon,France,FR
|
||||
Marseille,France,FR
|
||||
Toulouse,France,FR
|
||||
Nice,France,FR
|
||||
Rome,Italy,IT
|
||||
Milan,Italy,IT
|
||||
Naples,Italy,IT
|
||||
Turin,Italy,IT
|
||||
Florence,Italy,IT
|
||||
Madrid,Spain,ES
|
||||
Barcelona,Spain,ES
|
||||
Valencia,Spain,ES
|
||||
Seville,Spain,ES
|
||||
Bilbao,Spain,ES
|
||||
Sydney,Australia,AU
|
||||
Melbourne,Australia,AU
|
||||
Brisbane,Australia,AU
|
||||
Perth,Australia,AU
|
||||
Adelaide,Australia,AU
|
||||
Tokyo,Japan,JP
|
||||
Osaka,Japan,JP
|
||||
Kyoto,Japan,JP
|
||||
Yokohama,Japan,JP
|
||||
Nagoya,Japan,JP
|
||||
Beijing,China,CN
|
||||
Shanghai,China,CN
|
||||
Guangzhou,China,CN
|
||||
Shenzhen,China,CN
|
||||
Chengdu,China,CN
|
||||
Mumbai,India,IN
|
||||
Delhi,India,IN
|
||||
Bangalore,India,IN
|
||||
Hyderabad,India,IN
|
||||
Chennai,India,IN
|
||||
Sao Paulo,Brazil,BR
|
||||
Rio de Janeiro,Brazil,BR
|
||||
Brasilia,Brazil,BR
|
||||
Salvador,Brazil,BR
|
||||
Fortaleza,Brazil,BR
|
||||
Mexico City,Mexico,MX
|
||||
Guadalajara,Mexico,MX
|
||||
Monterrey,Mexico,MX
|
||||
Puebla,Mexico,MX
|
||||
Tijuana,Mexico,MX
|
||||
Moscow,Russia,RU
|
||||
Saint Petersburg,Russia,RU
|
||||
Novosibirsk,Russia,RU
|
||||
Yekaterinburg,Russia,RU
|
||||
Kazan,Russia,RU
|
||||
Lagos,Nigeria,NG
|
||||
Kano,Nigeria,NG
|
||||
Ibadan,Nigeria,NG
|
||||
Abuja,Nigeria,NG
|
||||
Port Harcourt,Nigeria,NG
|
||||
Karachi,Pakistan,PK
|
||||
Lahore,Pakistan,PK
|
||||
Islamabad,Pakistan,PK
|
||||
Rawalpindi,Pakistan,PK
|
||||
Faisalabad,Pakistan,PK
|
||||
Tehran,Iran,IR
|
||||
Mashhad,Iran,IR
|
||||
Isfahan,Iran,IR
|
||||
Karaj,Iran,IR
|
||||
Tabriz,Iran,IR
|
||||
Pyongyang,North Korea,KP
|
||||
Hamhung,North Korea,KP
|
||||
Chongjin,North Korea,KP
|
||||
Nampo,North Korea,KP
|
||||
Wonsan,North Korea,KP
|
||||
Damascus,Syria,SY
|
||||
Aleppo,Syria,SY
|
||||
Homs,Syria,SY
|
||||
Latakia,Syria,SY
|
||||
Hama,Syria,SY
|
||||
Caracas,Venezuela,VE
|
||||
Maracaibo,Venezuela,VE
|
||||
Valencia,Venezuela,VE
|
||||
Barquisimeto,Venezuela,VE
|
||||
Maracay,Venezuela,VE
|
||||
Havana,Cuba,CU
|
||||
Santiago de Cuba,Cuba,CU
|
||||
Camaguey,Cuba,CU
|
||||
Holguin,Cuba,CU
|
||||
Santa Clara,Cuba,CU
|
||||
Yangon,Myanmar,MM
|
||||
Mandalay,Myanmar,MM
|
||||
Naypyidaw,Myanmar,MM
|
||||
Mawlamyine,Myanmar,MM
|
||||
Bago,Myanmar,MM
|
||||
Kabul,Afghanistan,AF
|
||||
Kandahar,Afghanistan,AF
|
||||
Herat,Afghanistan,AF
|
||||
Mazar-i-Sharif,Afghanistan,AF
|
||||
Jalalabad,Afghanistan,AF
|
||||
Baghdad,Iraq,IQ
|
||||
Basra,Iraq,IQ
|
||||
Mosul,Iraq,IQ
|
||||
Erbil,Iraq,IQ
|
||||
Kirkuk,Iraq,IQ
|
||||
Tripoli,Libya,LY
|
||||
Benghazi,Libya,LY
|
||||
Misrata,Libya,LY
|
||||
Zawiya,Libya,LY
|
||||
Bayda,Libya,LY
|
||||
Khartoum,Sudan,SD
|
||||
Omdurman,Sudan,SD
|
||||
Port Sudan,Sudan,SD
|
||||
Kassala,Sudan,SD
|
||||
Nyala,Sudan,SD
|
||||
Mogadishu,Somalia,SO
|
||||
Hargeisa,Somalia,SO
|
||||
Bosaso,Somalia,SO
|
||||
Kismayo,Somalia,SO
|
||||
Merca,Somalia,SO
|
||||
Sanaa,Yemen,YE
|
||||
Aden,Yemen,YE
|
||||
Taiz,Yemen,YE
|
||||
Hodeidah,Yemen,YE
|
||||
Ibb,Yemen,YE
|
||||
Harare,Zimbabwe,ZW
|
||||
Bulawayo,Zimbabwe,ZW
|
||||
Chitungwiza,Zimbabwe,ZW
|
||||
Mutare,Zimbabwe,ZW
|
||||
Gweru,Zimbabwe,ZW
|
||||
Amsterdam,Netherlands,NL
|
||||
Rotterdam,Netherlands,NL
|
||||
The Hague,Netherlands,NL
|
||||
Utrecht,Netherlands,NL
|
||||
Eindhoven,Netherlands,NL
|
||||
Stockholm,Sweden,SE
|
||||
Gothenburg,Sweden,SE
|
||||
Malmo,Sweden,SE
|
||||
Uppsala,Sweden,SE
|
||||
Vasteras,Sweden,SE
|
||||
Oslo,Norway,NO
|
||||
Bergen,Norway,NO
|
||||
Trondheim,Norway,NO
|
||||
Stavanger,Norway,NO
|
||||
Drammen,Norway,NO
|
||||
Copenhagen,Denmark,DK
|
||||
Aarhus,Denmark,DK
|
||||
Odense,Denmark,DK
|
||||
Aalborg,Denmark,DK
|
||||
Esbjerg,Denmark,DK
|
||||
Helsinki,Finland,FI
|
||||
Espoo,Finland,FI
|
||||
Tampere,Finland,FI
|
||||
Vantaa,Finland,FI
|
||||
Oulu,Finland,FI
|
||||
Zurich,Switzerland,CH
|
||||
Geneva,Switzerland,CH
|
||||
Basel,Switzerland,CH
|
||||
Lausanne,Switzerland,CH
|
||||
Bern,Switzerland,CH
|
||||
Singapore,Singapore,SG
|
||||
Hong Kong,Hong Kong,HK
|
||||
Kowloon,Hong Kong,HK
|
||||
Seoul,South Korea,KR
|
||||
Busan,South Korea,KR
|
||||
Incheon,South Korea,KR
|
||||
Daegu,South Korea,KR
|
||||
Daejeon,South Korea,KR
|
||||
Taipei,Taiwan,TW
|
||||
Kaohsiung,Taiwan,TW
|
||||
Taichung,Taiwan,TW
|
||||
Tainan,Taiwan,TW
|
||||
Hsinchu,Taiwan,TW
|
||||
Auckland,New Zealand,NZ
|
||||
Wellington,New Zealand,NZ
|
||||
Christchurch,New Zealand,NZ
|
||||
Hamilton,New Zealand,NZ
|
||||
Tauranga,New Zealand,NZ
|
||||
|
||||
|
Reference in New Issue
Block a user