TutorialsAIPostgreSQLSQL

How to Build a Support Ticket Analytics Dashboard From Your Database

Customer support teams run on data. How many tickets came in today? Which categories are spiking? Which agents are resolving tickets fastest? Which issues st...

Marcus Chen· Solutions EngineerApril 6, 20267 min read

Customer support teams run on data. How many tickets came in today? Which categories are spiking? Which agents are resolving tickets fastest? Which issues stay open for days without anyone touching them?

Most support platforms give you some built-in reporting, but those reports are limited, slow to customize, and completely siloed from the rest of your business data. If your tickets live in a PostgreSQL database whether synced from Zendesk, Intercom, Freshdesk, or built in-house you already have everything you need to build a far more useful analytics dashboard.

This guide walks through building a support ticket analytics dashboard directly from your database. You will write the queries, understand the metrics that matter, and see how tools like AI for Database let you go from raw database access to a live, auto-refreshing dashboard without writing a single line of application code.

The Data Model: What Your Tickets Table Probably Looks Like

Before writing queries, it helps to establish a common baseline. Most support ticket databases whether you built your own or synced data from a third-party tool follow a structure similar to this:

CREATE TABLE tickets (
  id            SERIAL PRIMARY KEY,
  created_at    TIMESTAMP NOT NULL DEFAULT NOW(),
  updated_at    TIMESTAMP,
  resolved_at   TIMESTAMP,
  status        VARCHAR(20),     -- 'open', 'pending', 'resolved', 'closed'
  priority      VARCHAR(10),     -- 'p1', 'p2', 'p3', 'low', 'normal', 'high'
  category      VARCHAR(50),
  assigned_to   VARCHAR(100),    -- agent name or ID
  team          VARCHAR(50),
  customer_id   INT,
  subject       TEXT,
  channel       VARCHAR(20)      -- 'email', 'chat', 'phone', 'web'
);

Your schema will differ, but the concepts translate directly. The queries below use this structure. Adjust column names as needed.

Metric 1: Ticket Volume by Category

The most fundamental view is how tickets are distributed across categories. This tells you where customer pain concentrates.

SELECT
  category,
  COUNT(*) AS ticket_count,
  ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (), 1) AS pct_of_total
FROM tickets
WHERE created_at >= NOW() - INTERVAL '30 days'
GROUP BY category
ORDER BY ticket_count DESC;

This gives you both the raw count and each category's share of total volume. If "billing" jumps from 12% to 28% in a week, something changed a pricing update, an invoice bug, a billing cycle edge case. The dashboard surfaces that signal immediately.

Run this query weekly and you will start to see seasonal patterns, product release impacts, and the downstream effect of marketing campaigns.

Metric 2: Average Resolution Time by Team

Knowing that tickets exist is one thing. Knowing how fast they get resolved and which teams are slowest is where analytics becomes operational.

SELECT
  team,
  COUNT(*) AS resolved_tickets,
  ROUND(AVG(
    EXTRACT(EPOCH FROM (resolved_at - created_at)) / 3600
  ), 1) AS avg_hours_to_resolve,
  ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (
    ORDER BY EXTRACT(EPOCH FROM (resolved_at - created_at)) / 3600
  ), 1) AS median_hours_to_resolve
FROM tickets
WHERE
  resolved_at IS NOT NULL
  AND created_at >= NOW() - INTERVAL '30 days'
GROUP BY team
ORDER BY avg_hours_to_resolve ASC;

This query returns both mean and median resolution time. Median matters because a handful of very old tickets can inflate the average dramatically. If your median is 4 hours but your mean is 22 hours, you have a small number of tickets sitting unresolved for days which is a separate problem worth surfacing.

Metric 3: Open vs. Closed Tickets Over Time

A snapshot of your backlog at any given moment is useful. A trend over time tells you whether things are getting better or worse.

SELECT
  DATE_TRUNC('day', created_at) AS day,
  COUNT(*) FILTER (WHERE status IN ('open', 'pending')) AS opened,
  COUNT(*) FILTER (WHERE status IN ('resolved', 'closed')) AS closed
FROM tickets
WHERE created_at >= NOW() - INTERVAL '14 days'
GROUP BY DATE_TRUNC('day', created_at)
ORDER BY day ASC;

Charting this as a dual-line graph gives you an immediate visual of whether your team is keeping up with inbound volume. When the "opened" line consistently runs above "closed," your queue is growing. If you see that trend for three or four days in a row, that is your signal to staff up, triage more aggressively, or investigate why volume spiked.

Metric 4: Priority Distribution and SLA Compliance

Not all tickets are equal. P1 issues production outages, billing failures, data loss have much tighter SLA requirements than general inquiries. Your dashboard needs a clear view of how tickets break down by priority and whether high-priority issues are being handled within target windows.

SELECT
  priority,
  COUNT(*) AS total,
  COUNT(*) FILTER (WHERE status IN ('open', 'pending')) AS still_open,
  COUNT(*) FILTER (
    WHERE resolved_at IS NOT NULL
    AND EXTRACT(EPOCH FROM (resolved_at - created_at)) / 3600 <= CASE
      WHEN priority = 'p1' THEN 4
      WHEN priority = 'p2' THEN 24
      ELSE 72
    END
  ) AS resolved_within_sla
FROM tickets
WHERE created_at >= NOW() - INTERVAL '30 days'
GROUP BY priority
ORDER BY priority;

The CASE statement encodes your SLA targets directly into the query. P1 tickets should resolve within 4 hours, P2 within 24 hours, everything else within 72 hours. Adjust those numbers to match your actual SLA commitments.

This query is particularly useful for support leadership. If P1 SLA compliance drops below 90%, that conversation needs to happen today, not at the end of the month.

Metric 5: Agent Performance

Understanding which agents handle the most tickets and resolve them fastest helps with workforce planning, coaching, and identifying your top performers.

SELECT
  assigned_to AS agent,
  COUNT(*) AS tickets_handled,
  COUNT(*) FILTER (WHERE status IN ('resolved', 'closed')) AS tickets_resolved,
  ROUND(AVG(
    EXTRACT(EPOCH FROM (resolved_at - created_at)) / 3600
  ) FILTER (WHERE resolved_at IS NOT NULL), 1) AS avg_resolve_hours,
  COUNT(*) FILTER (WHERE status IN ('open', 'pending')) AS currently_open
FROM tickets
WHERE created_at >= NOW() - INTERVAL '30 days'
GROUP BY assigned_to
ORDER BY tickets_resolved DESC;

Read this table carefully. An agent with high volume and low resolve time is performing well. An agent with high volume and high resolve time may be overloaded or working on harder tickets. An agent with low volume and high open tickets may have a backlog building up quietly.

From Queries to a Live Dashboard

Writing these queries is the first step. The harder part is turning them into something useful a dashboard that refreshes automatically, is shareable with non-technical stakeholders, and does not require you to re-run queries manually every time someone wants an update.

This is exactly where AI for Database fits in.

Connect your database (PostgreSQL, MySQL, Supabase, BigQuery, and more are supported), and you can start asking questions in plain English:

  • "Show me average ticket resolution time by team for the last 30 days"
  • "Which categories had the most open P1 tickets this week?"
  • "How does this week's ticket volume compare to last week, broken down by channel?"
  • The tool translates those questions to SQL, runs them against your live database, and returns a table or chart. No query editor required for your ops manager or support lead.

    More importantly, you can save those queries as dashboard panels. The dashboard refreshes on a schedule hourly, daily, weekly so stakeholders always see current data without anyone having to manually run anything.

    The workflow feature takes this a step further. You can define conditions like: "when the count of open P1 tickets exceeds 10, send an alert to the support Slack channel." That runs automatically against your database on whatever interval you set. Your support manager gets notified before a P1 backlog becomes a crisis.

    Start Tracking What Actually Matters

    Support ticket analytics is not a reporting problem it is a visibility problem. The data is already in your database. The challenge is surfacing it quickly enough to be useful, and keeping it current without manual effort.

    The queries in this guide give you a solid analytical foundation: volume by category, resolution time by team, open vs. closed trends, priority distribution, SLA compliance, and agent performance. Build from these and add metrics that matter to your specific support operation.

    If you want to skip the dashboard infrastructure work and get straight to the insights, try AI for Database free at aifordatabase.com.

    Ready to try AI for Database?

    Query your database in plain English. No SQL required. Start free today.