DEV Community

Armaan Khan
Armaan Khan

Posted on

Dashboard 1

import streamlit as st
import pandas as pd
import json
from datetime import datetime

# Configure page
st.set_page_config(
    page_title="Snowflake Query Optimizer",
    page_icon="❄️",
    layout="wide",
    initial_sidebar_state="collapsed"
)

# Enhanced CSS for modern UI with proper table styling
st.markdown("""
<style>
    /* Import Google Fonts */
    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

    /* Reset and base styles */
    .main {
        padding: 1rem 2rem;
        font-family: 'Inter', sans-serif;
        background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
        min-height: 100vh;
    }

    /* Header with glassmorphism effect */
    .header-container {
        background: rgba(255, 255, 255, 0.25);
        backdrop-filter: blur(20px);
        border: 1px solid rgba(255, 255, 255, 0.18);
        padding: 3rem;
        border-radius: 25px;
        margin-bottom: 3rem;
        color: #2c3e50;
        text-align: center;
        box-shadow: 0 20px 40px rgba(0,0,0,0.1);
        position: relative;
        overflow: hidden;
    }

    .header-container::before {
        content: '';
        position: absolute;
        top: -50%;
        left: -50%;
        width: 200%;
        height: 200%;
        background: linear-gradient(45deg, transparent, rgba(255,255,255,0.1), transparent);
        animation: shimmer 3s infinite;
    }

    @keyframes shimmer {
        0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); }
        100% { transform: translateX(100%) translateY(100%) rotate(45deg); }
    }

    .header-title {
        font-size: 3.5rem;
        font-weight: 700;
        margin-bottom: 1rem;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        position: relative;
        z-index: 1;
    }

    .header-subtitle {
        font-size: 1.4rem;
        opacity: 0.8;
        font-weight: 400;
        color: #34495e;
        position: relative;
        z-index: 1;
    }

    /* Floating metrics cards with micro-interactions */
    .metrics-container {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
        gap: 1.5rem;
        margin-bottom: 3rem;
    }

    .metric-card {
        background: rgba(255, 255, 255, 0.9);
        backdrop-filter: blur(10px);
        padding: 2rem;
        border-radius: 20px;
        border: 1px solid rgba(255, 255, 255, 0.2);
        box-shadow: 0 8px 32px rgba(0,0,0,0.1);
        transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
        position: relative;
        overflow: hidden;
        cursor: pointer;
    }

    .metric-card:hover {
        transform: translateY(-10px) scale(1.02);
        box-shadow: 0 20px 60px rgba(0,0,0,0.15);
        background: rgba(255, 255, 255, 0.95);
    }

    .metric-card::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 4px;
        background: linear-gradient(90deg, #667eea, #764ba2, #f093fb, #f5576c);
        background-size: 400% 400%;
        animation: gradient 3s ease infinite;
    }

    @keyframes gradient {
        0% { background-position: 0% 50%; }
        50% { background-position: 100% 50%; }
        100% { background-position: 0% 50%; }
    }

    .metric-value {
        font-size: 2.8rem;
        font-weight: 700;
        color: #2c3e50;
        margin-bottom: 0.5rem;
        line-height: 1;
    }

    .metric-label {
        color: #7f8c8d;
        font-size: 0.95rem;
        text-transform: uppercase;
        letter-spacing: 1.5px;
        font-weight: 500;
    }

    /* Table container styling */
    .table-container {
        background: rgba(255, 255, 255, 0.95);
        backdrop-filter: blur(20px);
        border-radius: 25px;
        overflow: hidden;
        box-shadow: 0 20px 60px rgba(0,0,0,0.1);
        margin: 2rem 0;
        border: 1px solid rgba(255, 255, 255, 0.2);
    }

    .table-header {
        background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
        color: white;
        padding: 2rem;
        font-size: 1.5rem;
        font-weight: 600;
        text-align: center;
        position: relative;
        overflow: hidden;
    }

    .table-header::before {
        content: '';
        position: absolute;
        top: -2px;
        left: -2px;
        right: -2px;
        bottom: -2px;
        background: linear-gradient(45deg, #667eea, #764ba2, #f093fb, #f5576c);
        z-index: -1;
        animation: gradient 3s ease infinite;
    }

    /* Streamlit dataframe styling */
    .stDataFrame {
        border-radius: 0 0 25px 25px;
        overflow: hidden;
    }

    .stDataFrame > div {
        border-radius: 0 0 25px 25px;
    }

    /* Details page styling */
    .details-container {
        background: rgba(255, 255, 255, 0.95);
        backdrop-filter: blur(20px);
        border-radius: 25px;
        padding: 3rem;
        margin: 2rem 0;
        box-shadow: 0 20px 60px rgba(0,0,0,0.1);
        border: 1px solid rgba(255, 255, 255, 0.2);
    }

    .details-header {
        background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
        color: white;
        padding: 2rem;
        border-radius: 20px;
        margin-bottom: 2rem;
        text-align: center;
        position: relative;
        overflow: hidden;
    }

    .details-header::before {
        content: '';
        position: absolute;
        top: -50%;
        left: -50%;
        width: 200%;
        height: 200%;
        background: linear-gradient(45deg, transparent, rgba(255,255,255,0.1), transparent);
        animation: shimmer 3s infinite;
    }

    .query-box {
        background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
        border: 2px solid #dee2e6;
        border-radius: 15px;
        padding: 2rem;
        margin: 1.5rem 0;
        font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
        white-space: pre-wrap;
        max-height: 400px;
        overflow-y: auto;
        box-shadow: inset 0 4px 12px rgba(0,0,0,0.05);
        position: relative;
        font-size: 0.95rem;
        line-height: 1.5;
    }

    .query-box::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 4px;
        background: linear-gradient(90deg, #667eea, #764ba2);
        border-radius: 15px 15px 0 0;
    }

    /* Recommendations with enhanced styling */
    .recommendation-item {
        background: linear-gradient(135deg, #ffeaa7 0%, #fab1a0 100%);
        color: #2d3436;
        padding: 15px 25px;
        margin: 12px 0;
        border-radius: 25px;
        font-weight: 500;
        box-shadow: 0 6px 20px rgba(250, 177, 160, 0.3);
        transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
        position: relative;
        overflow: hidden;
    }

    .recommendation-item:hover {
        transform: translateX(15px) scale(1.02);
        box-shadow: 0 10px 30px rgba(250, 177, 160, 0.4);
    }

    .recommendation-item::before {
        content: '💡';
        position: absolute;
        left: -30px;
        top: 50%;
        transform: translateY(-50%);
        font-size: 1.2rem;
        transition: all 0.3s ease;
    }

    .recommendation-item:hover::before {
        left: 10px;
    }

    /* Back button with special styling */
    .stButton > button {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        border: none;
        border-radius: 12px;
        padding: 12px 20px;
        font-weight: 600;
        font-size: 1rem;
        transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
        width: 100%;
        margin: 4px;
        box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
        position: relative;
        overflow: hidden;
    }

    .stButton > button:hover {
        transform: translateY(-3px) scale(1.05);
        box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
        background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
    }

    /* Animation classes */
    .fadeInUp {
        animation: fadeInUp 0.8s ease-out;
    }

    .fadeInLeft {
        animation: fadeInLeft 0.8s ease-out;
    }

    .fadeInRight {
        animation: fadeInRight 0.8s ease-out;
    }

    @keyframes fadeInUp {
        from {
            opacity: 0;
            transform: translateY(40px);
        }
        to {
            opacity: 1;
            transform: translateY(0);
        }
    }

    @keyframes fadeInLeft {
        from {
            opacity: 0;
            transform: translateX(-40px);
        }
        to {
            opacity: 1;
            transform: translateX(0);
        }
    }

    @keyframes fadeInRight {
        from {
            opacity: 0;
            transform: translateX(40px);
        }
        to {
            opacity: 1;
            transform: translateX(0);
        }
    }

    /* Responsive design */
    @media (max-width: 768px) {
        .header-title {
            font-size: 2.5rem;
        }

        .metric-card {
            padding: 1.5rem;
        }
    }

    /* Custom styling for clickable cells */
    .clickable-info {
        background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
        color: #1565c0;
        padding: 1rem;
        border-radius: 10px;
        margin: 1rem 0;
        text-align: center;
        font-weight: 600;
        border: 2px solid #1976d2;
    }
</style>
""", unsafe_allow_html=True)

# Initialize session state
if 'page' not in st.session_state:
    st.session_state.page = 'overview'
if 'selected_user' not in st.session_state:
    st.session_state.selected_user = None
if 'selected_metric' not in st.session_state:
    st.session_state.selected_metric = None
if 'selected_count' not in st.session_state:
    st.session_state.selected_count = 0

# Sample data with all columns
def create_sample_data():
    """Create comprehensive sample data matching your query structure"""
    data = {
        'USER_NAME': ['john_doe', 'jane_smith', 'mike_wilson', 'sarah_jones', 'alex_brown', 'emma_davis', 'ryan_miller', 'lisa_taylor'],
        'TOTAL_QUERIES': [1250, 890, 2100, 567, 1800, 945, 1567, 723],
        'WAREHOUSES_USED': [3, 2, 5, 2, 4, 3, 4, 2],
        'DATABASES_ACCESSED': [4, 3, 6, 2, 5, 4, 5, 3],
        'TOTAL_CREDITS': [125.50, 89.30, 310.75, 45.20, 198.40, 112.80, 187.90, 78.60],
        'AVG_EXECUTION_TIME_MS': [2500, 1800, 4200, 1200, 3100, 2200, 2800, 1600],
        'AVG_BYTES_PER_ROW': [156.7, 123.4, 289.1, 98.2, 234.5, 145.8, 201.3, 112.6],
        'TOTAL_DATA_SCANNED_GB': [450.2, 320.8, 890.5, 180.3, 670.1, 380.4, 520.7, 290.1],
        'FAILURE_CANCELLATION_RATE_PCT': [2.5, 1.8, 5.2, 0.9, 3.1, 2.1, 3.8, 1.4],
        'SPILLED_QUERIES': [45, 23, 89, 12, 67, 34, 56, 19],
        'OVER_PROVISIONED_QUERIES': [67, 34, 123, 19, 89, 45, 78, 28],
        'PEAK_HOUR_LONG_RUNNING_QUERIES': [23, 15, 56, 8, 34, 18, 41, 12],
        'SELECT_STAR_QUERIES': [234, 156, 445, 89, 298, 178, 312, 134],
        'UNPARTITIONED_SCAN_QUERIES': [89, 45, 167, 23, 112, 67, 98, 41],
        'REPEATED_QUERIES': [345, 234, 567, 123, 456, 289, 398, 201],
        'COMPLEX_JOIN_QUERIES': [78, 45, 134, 23, 89, 56, 95, 38],
        'ZERO_RESULT_QUERIES': [34, 21, 78, 12, 45, 28, 52, 16],
        'HIGH_COMPILE_QUERIES': [56, 32, 98, 18, 67, 41, 73, 25],
        'UNTAGGED_QUERIES': [123, 87, 234, 45, 167, 98, 145, 76],
        'UNLIMITED_ORDER_BY_QUERIES': [23, 15, 45, 8, 32, 19, 28, 11],
        'LARGE_GROUP_BY_QUERIES': [34, 21, 67, 12, 45, 28, 39, 16],
        'SLOW_QUERIES': [78, 45, 134, 23, 89, 56, 95, 38],
        'EXPENSIVE_DISTINCT_QUERIES': [12, 8, 23, 4, 16, 10, 18, 6],
        'INEFFICIENT_LIKE_QUERIES': [45, 28, 78, 15, 56, 34, 49, 22],
        'NO_RESULTS_WITH_SCAN_QUERIES': [23, 15, 45, 8, 32, 19, 28, 11],
        'CARTESIAN_JOIN_QUERIES': [2, 1, 8, 0, 3, 1, 5, 0],
        'HIGH_COMPILE_RATIO_QUERIES': [15, 9, 28, 5, 19, 12, 21, 7],
        'WEIGHTED_SCORE': [1250.5, 890.2, 2100.8, 567.3, 1800.6, 945.7, 1567.4, 723.9],
        'COST_STATUS': ['Normal', 'Normal', 'High Cost', 'Normal', 'High Cost', 'Normal', 'High Cost', 'Normal'],
        'RECOMMENDATIONS': [
            ['Optimize memory usage or increase warehouse size', 'Specify columns instead of SELECT *'],
            ['Use smaller warehouses for simple queries', 'Implement query result caching'],
            ['Reduce data scanned with clustering', 'Schedule long queries off-peak', 'Avoid Cartesian products'],
            ['Apply query tags for cost attribution', 'Use materialized views for frequent queries'],
            ['Implement partitioning or clustering', 'Optimize slow-running queries', 'Review warehouse sizing'],
            ['Cache frequently accessed data', 'Use query result caching'],
            ['Optimize JOIN operations', 'Implement proper indexing strategies', 'Review query patterns'],
            ['Use column pruning techniques', 'Implement data compression']
        ],
        'QUERY_SAMPLES': [
            {
                'spilled': [
                    {'query_id': 'Q001', 'query_text': 'SELECT cu.customer_id, cu.customer_name, o.order_date, p.product_name\nFROM customers cu\nJOIN orders o ON cu.customer_id = o.customer_id\nJOIN order_items oi ON o.order_id = oi.order_id\nJOIN products p ON oi.product_id = p.product_id\nWHERE o.order_date >= \'2024-01-01\'\nORDER BY o.order_date DESC, cu.customer_name', 
                     'execution_time_ms': 45000, 'bytes_spilled_to_local_storage': 1000000}
                ],
                'select_star': [
                    {'query_id': 'Q002', 'query_text': 'SELECT * FROM user_activity_logs\nWHERE activity_date BETWEEN \'2024-01-01\' AND \'2024-12-31\'\nLIMIT 1000', 
                     'execution_time_ms': 12000, 'bytes_scanned': 500000000}
                ]
            },
            {
                'over_provisioned': [
                    {'query_id': 'Q003', 'query_text': 'SELECT COUNT(*) as total_users\nFROM users\nWHERE status = \'active\'', 
                     'execution_time_ms': 2000, 'warehouse_size': 'LARGE'}
                ]
            },
            {
                'peak_hour_long_running': [
                    {'query_id': 'Q004', 'query_text': 'SELECT \n    c.category_name,\n    COUNT(p.product_id) as product_count,\n    AVG(p.price) as avg_price,\n    SUM(oi.quantity * p.price) as total_revenue\nFROM categories c\nJOIN products p ON c.category_id = p.category_id\nJOIN order_items oi ON p.product_id = oi.product_id\nJOIN orders o ON oi.order_id = o.order_id\nWHERE o.order_date >= \'2023-01-01\'\nGROUP BY c.category_name\nORDER BY total_revenue DESC', 
                     'execution_time_ms': 450000, 'start_time': '2024-01-15 14:30:00'}
                ],
                'cartesian_join': [
                    {'query_id': 'Q005', 'query_text': 'SELECT u.username, p.product_name\nFROM users u\nCROSS JOIN products p\nWHERE u.created_date > \'2024-01-01\'', 
                     'execution_time_ms': 180000, 'rows_produced': 1000000}
                ]
            },
            {
                'zero_result': [
                    {'query_id': 'Q006', 'query_text': 'SELECT name, email, phone\nFROM customers\nWHERE status = \'inactive\'\n  AND last_login_date < \'2020-01-01\'\n  AND account_balance > 1000', 
                     'execution_time_ms': 5000}
                ]
            },
            {
                'unpartitioned_scan': [
                    {'query_id': 'Q007', 'query_text': 'SELECT \n    event_type,\n    COUNT(*) as event_count,\n    DATE_TRUNC(\'day\', event_timestamp) as event_date\nFROM system_events\nWHERE event_timestamp BETWEEN \'2024-01-01\' AND \'2024-12-31\'\n  AND severity_level = \'ERROR\'\nGROUP BY event_type, DATE_TRUNC(\'day\', event_timestamp)\nORDER BY event_date DESC, event_count DESC', 
                     'execution_time_ms': 89000, 'partitions_scanned': 365, 'partitions_total': 365}
                ],
                'slow_query': [
                    {'query_id': 'Q008', 'query_text': 'WITH customer_metrics AS (\n    SELECT \n        customer_id,\n        COUNT(order_id) as total_orders,\n        SUM(order_amount) as total_spent,\n        AVG(order_amount) as avg_order_value\n    FROM orders\n    WHERE order_date >= \'2023-01-01\'\n    GROUP BY customer_id\n),\nranked_customers AS (\n    SELECT *,\n        ROW_NUMBER() OVER (ORDER BY total_spent DESC) as spending_rank\n    FROM customer_metrics\n)\nSELECT c.customer_name, rc.*\nFROM ranked_customers rc\nJOIN customers c ON rc.customer_id = c.customer_id\nWHERE rc.total_spent > 10000\nORDER BY rc.spending_rank', 
                     'execution_time_ms': 125000, 'bytes_scanned': 2000000000}
                ]
            },
            # Add more sample data for other users
            {'over_provisioned': [{'query_id': 'Q009', 'query_text': 'SELECT status FROM orders LIMIT 10', 'execution_time_ms': 1500, 'warehouse_size': 'XLARGE'}]},
            {'select_star': [{'query_id': 'Q010', 'query_text': 'SELECT * FROM inventory WHERE stock_level < 10', 'execution_time_ms': 8000, 'bytes_scanned': 300000000}]},
            {'peak_hour_long_running': [{'query_id': 'Q011', 'query_text': 'SELECT region, SUM(sales) FROM sales_data GROUP BY region', 'execution_time_ms': 380000, 'start_time': '2024-02-10 15:45:00'}]}
        ]
    }
    return pd.DataFrame(data)

def render_header():
    """Render the enhanced header section"""
    st.markdown("""
    <div class="header-container fadeInUp">
        <div class="header-title">❄️ Snowflake Query Optimizer</div>
        <div class="header-subtitle">Advanced Query Performance Analysis & Optimization Dashboard</div>
    </div>
    """, unsafe_allow_html=True)

def render_overview_metrics(df):
    """Render overview metrics with enhanced styling"""
    st.markdown('<div class="metrics-container fadeInUp">', unsafe_allow_html=True)

    col1, col2, col3, col4 = st.columns(4)

    metrics = [
        (col1, len(df), "Total Users", "👥"),
        (col2, df['TOTAL_QUERIES'].sum(), "Total Queries", "🔍"),
        (col3, f"${df['TOTAL_CREDITS'].sum():.2f}", "Total Credits", "💰"),
        (col4, len(df[df['COST_STATUS'] == 'High Cost']), "High Cost Users", "⚠️")
    ]

    for col, value, label, icon in metrics:
        with col:
            st.markdown(f"""
            <div class="metric-card">
                <div class="metric-value">{icon} {value:}</div>
                <div class="metric-label">{label}</div>
            </div>
            """, unsafe_allow_html=True)

    st.markdown('</div>', unsafe_allow_html=True)

def handle_cell_click(user_name, metric_name, count):
    """Handle cell click by updating session state"""
    st.session_state.page = 'details'
    st.session_state.selected_user = user_name
    st.session_state.selected_metric = metric_name
    st.session_state.selected_count = count

def format_dataframe_for_display(df):
    """Format the dataframe for better display"""
    # Get all columns except the ones we want to exclude
    exclude_columns = ['RECOMMENDATIONS', 'QUERY_SAMPLES']
    display_df = df[[col for col in df.columns if col not in exclude_columns]].copy()

    # Format numeric columns for better display
    for col in display_df.columns:
        if col in ['TOTAL_CREDITS']:
            display_df[col] = display_df[col].apply(lambda x: f"${x:.2f}")
        elif col in ['AVG_EXECUTION_TIME_MS']:
            display_df[col] = display_df[col].apply(lambda x: f"{x:,.0f}ms")
        elif col in ['TOTAL_DATA_SCANNED_GB']:
            display_df[col] = display_df[col].apply(lambda x: f"{x:.1f}GB")
        elif col in ['FAILURE_CANCELLATION_RATE_PCT']:
            display_df[col] = display_df[col].apply(lambda x: f"{x:.1f}%")
        elif col in ['AVG_BYTES_PER_ROW']:
            display_df[col] = display_df[col].apply(lambda x: f"{x:.1f}B")
        elif col in ['WEIGHTED_SCORE']:
            display_df[col] = display_df[col].apply(lambda x: f"{x:.1f}")
        elif col == 'COST_STATUS':
            display_df[col] = display_df[col].apply(lambda x: f"{'🔥' if x == 'High Cost' else '✅'} {x}")
        elif col == 'USER_NAME':
            display_df[col] = display_df[col].apply(lambda x: f"👤 {x}")
        elif isinstance(display_df[col].iloc[0], (int, float)) and col not in ['TOTAL_CREDITS', 'AVG_EXECUTION_TIME_MS', 'TOTAL_DATA_SCANNED_GB', 'FAILURE_CANCELLATION_RATE_PCT', 'AVG_BYTES_PER_ROW', 'WEIGHTED_SCORE']:
            display_df[col] = display_df[col].apply(lambda x: f"{x:,}")

    # Rename columns for better display
    column_mapping = {
        'USER_NAME': '👤 User',
        'TOTAL_QUERIES': 'Total Queries',
        'WAREHOUSES_USED': 'Warehouses',
        'DATABASES_ACCESSED': 'Databases',
        'TOTAL_CREDITS': '💰 Credits',
        'AVG_EXECUTION_TIME_MS': '⏱️ Avg Time',
        'AVG_BYTES_PER_ROW': '📊 Bytes/Row',
        'TOTAL_DATA_SCANNED_GB': '📈 Data Scanned',
        'FAILURE_CANCELLATION_RATE_PCT': '❌ Failure Rate',
        'SPILLED_QUERIES': '💾 Spilled',
        'OVER_PROVISIONED_QUERIES': '📈 Over Prov.',
        'PEAK_HOUR_LONG_RUNNING_QUERIES': '⏰ Peak Long',
        'SELECT_STAR_QUERIES': '⭐ Select *',
        'UNPARTITIONED_SCAN_QUERIES': '🔍 Unpart. Scan',
        'REPEATED_QUERIES': '🔄 Repeated',
        'COMPLEX_JOIN_QUERIES': '🔗 Complex Join',
        'ZERO_RESULT_QUERIES': '🚫 Zero Results',
        'HIGH_COMPILE_QUERIES': '⚙️ High Compile',
        'UNTAGGED_QUERIES': '🏷️ Untagged',
        'UNLIMITED_ORDER_BY_QUERIES': '📊 Unlim. Order',
        'LARGE_GROUP_BY_QUERIES': '📈 Large Group',
        'SLOW_QUERIES': '🐌 Slow',
        'EXPENSIVE_DISTINCT_QUERIES': '💎 Exp. Distinct',
        'INEFFICIENT_LIKE_QUERIES': '🔍 Ineffic. Like',
        'NO_RESULTS_WITH_SCAN_QUERIES': '🚫 No Results',
        'CARTESIAN_JOIN_QUERIES': '🔗 Cartesian',
        'HIGH_COMPILE_RATIO_QUERIES': '⚙️ High Ratio',
        'WEIGHTED_SCORE': '🎯 Score',
        'COST_STATUS': '💸 Status'
    }

    display_df = display_df.rename(columns=column_mapping)

    return display_df

def render_interactive_table(df):
    """Render an interactive table using Streamlit's native components"""
    st.markdown('<div class="table-container fadeInUp">', unsafe_allow_html=True)
    st.markdown('<div class="table-header">🎯 Complete Query Performance Analysis</div>', unsafe_allow_html=True)

    # Format the dataframe for display
    display_df = format_dataframe_for_display(df)

    # Show instructions
    st.markdown("""
    <div class="clickable-info">
        📌 <strong>How to interact:</strong> Click on any row in the table below to select a user, then use the metric buttons to view detailed analysis.
    </div>
    """, unsafe_allow_html=True)

    # Display the dataframe with selection
    selected_rows = st.dataframe(
        display_df,
        use_container_width=True,
        hide_index=True,
        on_select="rerun",
        selection_mode="single-row",
        height=400
    )

    st.markdown('</div>', unsafe_allow_html=True)

    # Handle row selection
    if selected_rows.selection.rows:
        selected_idx = selected_rows.selection.rows[0]
        selected_user = df.iloc[selected_idx]['USER_NAME']

        st.markdown(f"""
        <div class="clickable-info">
            🎯 <strong>Selected User:</strong> {selected_user} - Click on any metric below to view detailed analysis
        </div>
        """, unsafe_allow_html=True)

        # Define clickable metrics
        clickable_metrics = [
            ('SPILLED_QUERIES', '💾 Spilled Queries'),
            ('OVER_PROVISIONED_QUERIES', '📈 Over Provisioned'),
            ('PEAK_HOUR_LONG_RUNNING_QUERIES', '⏰ Peak Long Running'),
            ('SELECT_STAR_QUERIES', '⭐ Select * Queries'),
            ('UNPARTITIONED_SCAN_QUERIES', '🔍 Unpartitioned Scan'),
            ('REPEATED_QUERIES', '🔄 Repeated Queries'),
            ('COMPLEX_JOIN_QUERIES', '🔗 Complex Joins'),
            ('ZERO_RESULT_QUERIES', '🚫 Zero Result Queries'),
            ('HIGH_COMPILE_QUERIES', '⚙️ High Compile Time'),
            ('UNTAGGED_QUERIES', '🏷️ Untagged Queries'),
            ('UNLIMITED_ORDER_BY_QUERIES', '📊 Unlimited Order By'),
            ('LARGE_GROUP_BY_QUERIES', '📈 Large Group By'),
            ('SLOW_QUERIES', '🐌 Slow Queries'),
            ('EXPENSIVE_DISTINCT_QUERIES', '💎 Expensive Distinct'),
            ('INEFFICIENT_LIKE_QUERIES', '🔍 Inefficient Like'),
            ('NO_RESULTS_WITH_SCAN_QUERIES', '🚫 No Results with Scan'),
            ('CARTESIAN_JOIN_QUERIES', '🔗 Cartesian Joins'),
            ('HIGH_COMPILE_RATIO_QUERIES', '⚙️ High Compile Ratio')
        ]

        # Create metric buttons in a grid
        cols = st.columns(6)  # 6 columns for better layout

        for i, (metric_col, metric_label) in enumerate(clickable_metrics):
            col_idx = i % 6
            value = int(df.iloc[selected_idx][metric_col])

            with cols[col_idx]:
                if value > 0:
                    if st.button(
                        f"{metric_label}\n{value:,}",
                        key=f"metric_{selected_user}_{metric_col}",
                        help=f"View {value} {metric_label.lower()}",
                        use_container_width=True,
                        type="primary"
                    ):
                        handle_cell_click(selected_user, metric_col, value)
                        st.rerun()
                else:
                    st.button(
                        f"{metric_label}\n{value}",
                        key=f"metric_zero_{selected_user}_{metric_col}",
                        disabled=True,
                        use_container_width=True,
                        help="No queries of this type"
                    )
    else:
        st.markdown("""
        <div class="clickable-info">
            👆 <strong>Select a user:</strong> Click on any row in the table above to view available metrics for that user
        </div>
        """, unsafe_allow_html=True)

def render_query_details(df, user_name, metric_name, count):
    """Render detailed query information with enhanced UI"""
    # Enhanced back button
    col1, col2, col3 = st.columns([1, 2, 1])
    with col1:
        if st.button("← Back to Overview", key="back_button", help="Return to main dashboard", use_container_width=True):
            st.session_state.page = 'overview'
            st.rerun()

    # Get user data
    user_data = df[df['USER_NAME'] == user_name].iloc[0]

    # Enhanced header with animation
    metric_display_name = metric_name.replace('_', ' ').title()
    metric_icon = {
        'SPILLED_QUERIES': '💾',
        'OVER_PROVISIONED_QUERIES': '📈',
        'PEAK_HOUR_LONG_RUNNING_QUERIES': '⏰',
        'SELECT_STAR_QUERIES': '⭐',
        'UNPARTITIONED_SCAN_QUERIES': '🔍',
        'ZERO_RESULT_QUERIES': '🚫',
        'SLOW_QUERIES': '🐌',
        'CARTESIAN_JOIN_QUERIES': '🔗',
        'REPEATED_QUERIES': '🔄',
        'COMPLEX_JOIN_QUERIES': '🔗',
        'HIGH_COMPILE_QUERIES': '⚙️',
        'UNTAGGED_QUERIES': '🏷️',
        'UNLIMITED_ORDER_BY_QUERIES': '📊',
        'LARGE_GROUP_BY_QUERIES': '📈',
        'EXPENSIVE_DISTINCT_QUERIES': '💎',
        'INEFFICIENT_LIKE_QUERIES': '🔍',
        'NO_RESULTS_WITH_SCAN_QUERIES': '🚫',
        'HIGH_COMPILE_RATIO_QUERIES': '⚙️'
    }.get(metric_name, '📊')

    st.markdown(f"""
    <div class="details-container fadeInUp">
        <div class="details-header">
            <h1>{metric_icon} {user_name}</h1>
            <h2>{metric_display_name}</h2>
            <p style="font-size: 1.2rem; margin-top: 1rem; opacity: 0.9;">
                Found <strong>{count:,}</strong> queries of this type
            </p>
        </div>
    </div>
    """, unsafe_allow_html=True)

    # Enhanced user overview metrics
    st.markdown("### 📈 User Performance Overview")
    col1, col2, col3, col4 = st.columns(4)

    metrics_data = [
        (col1, "Total Queries", f"{user_data['TOTAL_QUERIES']:,}", "🔍"),
        (col2, "Total Credits", f"${user_data['TOTAL_CREDITS']:.2f}", "💰"),
        (col3, "Cost Status", user_data['COST_STATUS'], "💸"),
        (col4, "Current Issue", f"{count:,} {metric_display_name}", metric_icon)
    ]

    for col, label, value, icon in metrics_data:
        with col:
            st.markdown(f"""
            <div class="metric-card fadeInUp">
                <div class="metric-value">{icon} {value}</div>
                <div class="metric-label">{label}</div>
            </div>
            """, unsafe_allow_html=True)

    # Enhanced recommendations section
    if user_data['RECOMMENDATIONS']:
        st.markdown("### 🎯 Optimization Recommendations")
        st.markdown('<div class="fadeInLeft">', unsafe_allow_html=True)
        for i, rec in enumerate(user_data['RECOMMENDATIONS']):
            st.markdown(f'<div class="recommendation-item" style="animation-delay: {i*0.1}s;">{rec}</div>', unsafe_allow_html=True)
        st.markdown('</div>', unsafe_allow_html=True)

    # Enhanced sample queries section
    st.markdown("### 📋 Sample Query Analysis")

    # Get query samples for this metric
    query_samples = user_data['QUERY_SAMPLES']
    if isinstance(query_samples, dict):
        # Map metric names to sample keys
        metric_key_mapping = {
            'SPILLED_QUERIES': 'spilled',
            'OVER_PROVISIONED_QUERIES': 'over_provisioned',
            'PEAK_HOUR_LONG_RUNNING_QUERIES': 'peak_hour_long_running',
            'SELECT_STAR_QUERIES': 'select_star',
            'UNPARTITIONED_SCAN_QUERIES': 'unpartitioned_scan',
            'ZERO_RESULT_QUERIES': 'zero_result',
            'SLOW_QUERIES': 'slow_query',
            'CARTESIAN_JOIN_QUERIES': 'cartesian_join',
            'REPEATED_QUERIES': 'repeated',
            'COMPLEX_JOIN_QUERIES': 'complex_join',
            'HIGH_COMPILE_QUERIES': 'high_compile',
            'UNTAGGED_QUERIES': 'untagged',
            'UNLIMITED_ORDER_BY_QUERIES': 'unlimited_order_by',
            'LARGE_GROUP_BY_QUERIES': 'large_group_by',
            'EXPENSIVE_DISTINCT_QUERIES': 'expensive_distinct',
            'INEFFICIENT_LIKE_QUERIES': 'inefficient_like',
            'NO_RESULTS_WITH_SCAN_QUERIES': 'no_results_with_scan',
            'HIGH_COMPILE_RATIO_QUERIES': 'high_compile_ratio'
        }

        metric_key = metric_key_mapping.get(metric_name)

        if metric_key and metric_key in query_samples and query_samples[metric_key]:
            samples = query_samples[metric_key]

            for i, query in enumerate(samples[:3]):  # Show up to 3 samples
                with st.expander(f"🔍 Query Sample {i+1}: {query['query_id']}", expanded=(i==0)):
                    col1, col2 = st.columns([2.5, 1])

                    with col1:
                        st.markdown("**📝 Query Text:**")
                        st.markdown(f'<div class="query-box fadeInUp">{query["query_text"]}</div>', unsafe_allow_html=True)

                    with col2:
                        st.markdown("**📊 Performance Metrics:**")

                        # Create metric cards for query details
                        if 'execution_time_ms' in query:
                            st.markdown(f"""
                            <div class="metric-card" style="margin-bottom: 1rem;">
                                <div class="metric-value">⏱️ {query['execution_time_ms']:,}ms</div>
                                <div class="metric-label">Execution Time</div>
                            </div>
                            """, unsafe_allow_html=True)

                        if 'bytes_scanned' in query:
                            bytes_gb = query['bytes_scanned'] / (1024**3)
                            st.markdown(f"""
                            <div class="metric-card" style="margin-bottom: 1rem;">
                                <div class="metric-value">📊 {bytes_gb:.2f}GB</div>
                                <div class="metric-label">Data Scanned</div>
                            </div>
                            """, unsafe_allow_html=True)

                        if 'warehouse_size' in query:
                            st.markdown(f"""
                            <div class="metric-card" style="margin-bottom: 1rem;">
                                <div class="metric-value">🏭 {query['warehouse_size']}</div>
                                <div class="metric-label">Warehouse Size</div>
                            </div>
                            """, unsafe_allow_html=True)

                        if 'rows_produced' in query:
                            st.markdown(f"""
                            <div class="metric-card" style="margin-bottom: 1rem;">
                                <div class="metric-value">📈 {query['rows_produced']:,}</div>
                                <div class="metric-label">Rows Produced</div>
                            </div>
                            """, unsafe_allow_html=True)

                        if 'bytes_spilled_to_local_storage' in query:
                            spilled_mb = query['bytes_spilled_to_local_storage'] / (1024**2)
                            st.markdown(f"""
                            <div class="metric-card" style="margin-bottom: 1rem;">
                                <div class="metric-value">💾 {spilled_mb:.1f}MB</div>
                                <div class="metric-label">Spilled to Storage</div>
                            </div>
                            """, unsafe_allow_html=True)

                        if 'partitions_scanned' in query and 'partitions_total' in query:
                            efficiency = (1 - query['partitions_scanned'] / query['partitions_total']) * 100
                            st.markdown(f"""
                            <div class="metric-card" style="margin-bottom: 1rem;">
                                <div class="metric-value">🎯 {efficiency:.1f}%</div>
                                <div class="metric-label">Partition Efficiency</div>
                            </div>
                            """, unsafe_allow_html=True)

                        if 'start_time' in query:
                            st.markdown(f"""
                            <div class="metric-card" style="margin-bottom: 1rem;">
                                <div class="metric-value">🕐 {query['start_time']}</div>
                                <div class="metric-label">Start Time</div>
                            </div>
                            """, unsafe_allow_html=True)
        else:
            st.markdown("""
            <div style="text-align: center; padding: 3rem; background: rgba(255, 255, 255, 0.8); border-radius: 15px; margin: 2rem 0;">
                <h3>🔍 No Sample Queries Available</h3>
                <p style="color: #7f8c8d; font-size: 1.1rem;">
                    Sample queries for this metric are not available in the current dataset.
                </p>
            </div>
            """, unsafe_allow_html=True)
    else:
        st.markdown("""
        <div style="text-align: center; padding: 3rem; background: rgba(255, 255, 255, 0.8); border-radius: 15px; margin: 2rem 0;">
            <h3>🔍 Query Data Unavailable</h3>
            <p style="color: #7f8c8d; font-size: 1.1rem;">
                Query sample data structure needs to be updated for this user.
            </p>
        </div>
        """, unsafe_allow_html=True)

# Main application logic
def main():
    # Load data
    df = create_sample_data()

    # Render header
    render_header()

    # Route to appropriate page
    if st.session_state.page == 'overview':
        render_overview_metrics(df)
        render_interactive_table(df)

        # Add footer with additional info
        st.markdown("""
        <div style="text-align: center; margin-top: 3rem; padding: 2rem; background: rgba(255, 255, 255, 0.8); border-radius: 15px;">
            <h4 style="color: #2c3e50; margin-bottom: 1rem;">💡 How to Use This Dashboard</h4>
            <p style="color: #7f8c8d; font-size: 1rem; line-height: 1.6;">
                <strong>Step 1:</strong> Click on any row in the table to select a user<br>
                <strong>Step 2:</strong> Click on any metric button below the table to view detailed analysis<br>
                <strong>Step 3:</strong> Explore query samples and optimization recommendations
            </p>
        </div>
        """, unsafe_allow_html=True)

    elif st.session_state.page == 'details':
        render_query_details(
            df, 
            st.session_state.selected_user, 
            st.session_state.selected_metric,
            st.session_state.selected_count
        )

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

Top comments (0)