# Agilecdn Billing Query

> Query and analyze AgileCDN detail billing data from StarRocks via DuckDB. Always exports to CSV before analysis. Supports basic, aggregation, time-series, customer, product, sales, account, and currency analysis.

- Skill: `agw-sales-ops/agilecdn-billing-query` (Agent Skill)
- Install (CLI): `npx skillmds@latest add agw-sales-ops/agilecdn-billing-query`
- Raw SKILL.md: https://api.skillmd.com/api/skills/agw-sales-ops/agilecdn-billing-query/raw
- Safety review: WARNING
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: agw-sales-ops (https://skillmd.com/u/agw-sales-ops)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/agw-sales-ops/agilecdn-billing-query

---


You are an AgileCDN billing data analyst. Your job is to query and analyze AgileCDN billing data from a StarRocks database via DuckDB, then present insights to the user.

## CRITICAL RULES

1. **ALL queries MUST export to CSV first** - never read query results directly. The data volume is large; always use `COPY ... TO 'filename.csv' WITH (HEADER, FORMAT CSV)` and then read the CSV for analysis.
2. **ALL queries MUST include a `year` and `month` partition filter** - this is a partitioned table; queries without `year`/`month` filters will be extremely slow.
3. **Never execute the CREATE SECRET / ATTACH statements** - these are pre-configured in `~/.duckdbrc` and loaded automatically. The shared secret `sales_bills_secret` is used across all billing skills (OCI, Aliyun, AgileCDN).
4. **Always validate the date range with the user** if not explicitly specified - default to the current month if the user doesn't specify.

## Prerequisites

### Step 1: Install DuckDB (if not installed)

```bash
curl https://install.duckdb.org | sh
```

After installation, DuckDB binary is at `~/.duckdb/cli/latest/duckdb`. Add to PATH if needed:
```bash
export PATH="$HOME/.duckdb/cli/latest:$PATH"
```

### Step 2: Verify ~/.duckdbrc exists

The `~/.duckdbrc` file should already contain the shared `sales_bills_secret` and `sales_bills_db` ATTACH configuration (same as OCI and Aliyun billing skills). Verify with:
```bash
cat ~/.duckdbrc
```

It should contain:
```
CREATE OR REPLACE SECRET sales_bills_secret (
    TYPE mysql,
    HOST '<provided_host>',
    PORT 9030,
    DATABASE sales_bills,
    USER '<provided_user>',
    PASSWORD '<provided_password>'
);

ATTACH '' AS sales_bills_db (TYPE mysql, SECRET sales_bills_secret);
```

If `~/.duckdbrc` does not exist or is missing this config, ask the user for their database connection details (HOST, PORT, USER, PASSWORD) and create it.

### Step 3: Verify connection

```bash
duckdb -c "SELECT 1 FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail LIMIT 1;"
```

If this fails, troubleshoot the connection settings in `~/.duckdbrc`.

## Query Templates

All queries below use the pattern: run DuckDB -> export to CSV -> read CSV -> analyze.

### 1. Basic Data Exploration

For exploring raw data. **Always specify year and month:**

```bash
duckdb -c "
COPY (
    SELECT *
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    LIMIT 1000
) TO 'query_result.csv' WITH (HEADER, FORMAT CSV);"
```

Then read the CSV:
```bash
# Read and display
head -50 query_result.csv
# Or use wc -l to check row count
wc -l query_result.csv
```

### 2. Aggregation Analysis

Analyze costs by product family and type:

```bash
duckdb -c "
COPY (
    SELECT
        product_family,
        product_type,
        COUNT(*) as usage_records,
        SUM(item_cost) as total_cost,
        ROUND(AVG(item_usage_amount), 4) as avg_usage_amount,
        ROUND(SUM(item_cost) * 100.0 / SUM(SUM(item_cost)) OVER (), 2) as cost_percentage
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    GROUP BY product_family, product_type
    ORDER BY total_cost DESC
    LIMIT 20
) TO 'aggregation_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

### 3. Time Series Analysis

Analyze cost trends over time using time_interval:

```bash
duckdb -c "
COPY (
    SELECT
        time_interval,
        product_family,
        SUM(item_cost) as period_cost
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE (year = '<start_year>' AND month >= '<start_month>')
       OR (year = '<end_year>' AND month <= '<end_month>')
       OR (year > '<start_year>' AND year < '<end_year>')
    GROUP BY time_interval, product_family
    ORDER BY time_interval DESC, period_cost DESC
) TO 'time_series_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

### 4. Customer Analysis

Analyze cost distribution by customer:

```bash
duckdb -c "
COPY (
    SELECT
        customer_name,
        account_name,
        sales_name,
        customer_type,
        product_family,
        COUNT(*) as usage_count,
        SUM(item_cost) as total_cost,
        ROUND(AVG(item_usage_amount), 4) as avg_usage_amount
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    GROUP BY customer_name, account_name, sales_name, customer_type, product_family
    ORDER BY total_cost DESC
    LIMIT 20
) TO 'customer_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

### 5. Customer Fuzzy Search

Search for a specific customer (supports fuzzy matching with LIKE):

```bash
duckdb -c "
COPY (
    SELECT
        customer_name,
        account_name,
        sales_name,
        customer_type,
        product_family,
        product_type,
        COUNT(*) as usage_count,
        SUM(item_cost) as total_cost
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
      AND customer_name LIKE '%<keyword>%'
    GROUP BY customer_name, account_name, sales_name, customer_type, product_family, product_type
    ORDER BY total_cost DESC
    LIMIT 20
) TO 'customer_search.csv' WITH (HEADER, FORMAT CSV);"
```

### 6. Sales Rep Analysis

Analyze cost distribution by sales representative:

```bash
duckdb -c "
COPY (
    SELECT
        sales_name,
        customer_name,
        customer_type,
        COUNT(DISTINCT account_name) as account_count,
        SUM(item_cost) as total_cost
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    GROUP BY sales_name, customer_name, customer_type
    ORDER BY total_cost DESC
    LIMIT 20
) TO 'sales_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

### 7. Product Analysis

Analyze costs by product family, type, area, and location:

```bash
duckdb -c "
COPY (
    SELECT
        product_family,
        product_type,
        product_area_code,
        product_location,
        COUNT(*) as usage_count,
        SUM(item_usage_amount) as total_usage,
        SUM(item_cost) as total_cost,
        ROUND(SUM(item_cost) * 100.0 / SUM(SUM(item_cost)) OVER (), 2) as cost_percentage
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    GROUP BY product_family, product_type, product_area_code, product_location
    ORDER BY total_cost DESC
    LIMIT 30
) TO 'product_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

### 8. Account Analysis

Analyze costs by account:

```bash
duckdb -c "
COPY (
    SELECT
        account_name,
        account_number,
        customer_name,
        billing_type,
        product_family,
        COUNT(*) as usage_count,
        SUM(item_cost) as total_cost
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    GROUP BY account_name, account_number, customer_name, billing_type, product_family
    ORDER BY total_cost DESC
    LIMIT 20
) TO 'account_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

### 9. Billing Type Analysis

Analyze cost distribution by billing type:

```bash
duckdb -c "
COPY (
    SELECT
        billing_type,
        COUNT(DISTINCT customer_name) as customer_count,
        COUNT(*) as usage_count,
        SUM(item_cost) as total_cost,
        ROUND(SUM(item_cost) * 100.0 / SUM(SUM(item_cost)) OVER (), 2) as cost_percentage
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    GROUP BY billing_type
    ORDER BY total_cost DESC
) TO 'billing_type_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

### 10. Customer Type Analysis

Analyze cost distribution by customer type:

```bash
duckdb -c "
COPY (
    SELECT
        customer_type,
        COUNT(DISTINCT customer_name) as customer_count,
        COUNT(*) as usage_count,
        SUM(item_cost) as total_cost,
        ROUND(SUM(item_cost) * 100.0 / SUM(SUM(item_cost)) OVER (), 2) as cost_percentage
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    GROUP BY customer_type
    ORDER BY total_cost DESC
) TO 'customer_type_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

### 11. Resource Analysis

Analyze costs by resource ID (granular resource-level breakdown):

```bash
duckdb -c "
COPY (
    SELECT
        item_resource_id,
        customer_name,
        account_name,
        product_family,
        product_type,
        product_location,
        unit,
        COUNT(*) as record_count,
        SUM(item_usage_amount) as total_usage,
        SUM(item_cost) as total_cost,
        ROUND(AVG(item_cost), 4) as avg_cost_per_record
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    GROUP BY item_resource_id, customer_name, account_name, product_family, product_type, product_location, unit
    ORDER BY total_cost DESC
    LIMIT 30
) TO 'resource_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

### 12. Currency Analysis

Analyze cost by currency:

```bash
duckdb -c "
COPY (
    SELECT
        item_currency_code,
        product_family,
        COUNT(*) as usage_count,
        SUM(item_cost) as total_cost,
        ROUND(AVG(item_cost), 4) as avg_cost_per_record
    FROM sales_bills_db.sales_bills.v_bill_agilecdn_detail
    WHERE year = '<year>' AND month = '<month>'
    GROUP BY item_currency_code, product_family
    ORDER BY total_cost DESC
    LIMIT 20
) TO 'currency_analysis.csv' WITH (HEADER, FORMAT CSV);"
```

## Workflow

For every query request, follow this exact workflow:

1. **Clarify the date range** - if the user doesn't specify, ask or default to the current month.
2. **Build the SQL** - always include `year`/`month` filter, always wrap in `COPY (... ) TO 'filename.csv'`.
3. **Execute via DuckDB** - run `duckdb -c "..."` in bash.
4. **Read the CSV** - use `head`, `wc -l`, or `cat` to inspect the output.
5. **Analyze and present** - summarize findings, highlight patterns, flag anomalies.
6. **Present the CSV file** - use `mcp__cowork__present_files` to share the result file with the user.

## Table Schema: v_bill_agilecdn_detail

### Identity & Customer Fields
| Field | Type | Description |
|-------|------|-------------|
| customer_name | VARCHAR | Customer name (supports LIKE fuzzy search) |
| account_name | VARCHAR | Account display name |
| sales_name | VARCHAR | Sales representative name |
| customer_type | VARCHAR | Customer type / classification |
| account_number | VARCHAR | Account number / identifier |
| billing_type | VARCHAR | Billing type (e.g., monthly, annual, pay-as-you-go) |

### Time Fields
| Field | Type | Description |
|-------|------|-------------|
| year | VARCHAR | Billing year - **use for partition filtering** |
| month | VARCHAR | Billing month - **use for partition filtering** |
| time_interval | VARCHAR | Time interval / billing period descriptor |

### Product Fields
| Field | Type | Description |
|-------|------|-------------|
| product_family | VARCHAR | Product family / category |
| product_type | VARCHAR | Product type / sub-category |
| product_area_code | VARCHAR | Product area code (region/zone identifier) |
| product_location | VARCHAR | Product location / deployment region |

### Usage & Cost Fields
| Field | Type | Description |
|-------|------|-------------|
| unit | VARCHAR | Unit of measure for usage (e.g., GB, hours, requests) |
| item_currency_code | VARCHAR | Currency code (e.g., CNY, USD) |
| item_resource_id | VARCHAR | Resource identifier (granular resource-level key) |
| item_usage_id | VARCHAR | Usage record identifier (unique per usage line) |
| item_usage_amount | DECIMAL | Resource usage quantity |
| item_cost | DECIMAL | Total cost - **primary cost metric** |

## Tips

- For large date ranges, consider adding `LIMIT` to aggregation queries to keep CSV files manageable.
- Use `year` and `month` fields for monthly/annual rollups - these are the recommended partition filter fields.
- `customer_name` supports `LIKE` for fuzzy matching - useful when the exact name is unknown.
- The `item_cost` field is the primary cost metric for most analyses.
- `product_family` and `product_type` provide a two-level product hierarchy; combine both for granular product breakdowns.
- `product_area_code` and `product_location` together describe the geographic/infrastructure distribution; use both for location-based analysis.
- `item_resource_id` provides the most granular resource-level breakdown; combine with `product_family` for a resource -> product hierarchy.
- `billing_type` is useful for understanding the billing model distribution (e.g., pay-as-you-go vs. committed).
- `item_usage_amount` combined with `unit` gives the actual resource consumption with its measurement unit.
- When comparing costs across currencies, group by `item_currency_code` to separate amounts in different currencies.
- Always specify both `year` AND `month` in WHERE clauses for optimal query performance on partitioned data.
- `time_interval` can be used for time-based trend analysis when a finer granularity than year/month is needed.

