@quarri/claude-data-tools 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,328 @@
1
+ ---
2
+ description: Statistical analysis and business insights from data
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # /quarri-insights - Statistical Analysis & Business Insights
8
+
9
+ Perform statistical analysis on data and generate actionable business insights with recommendations.
10
+
11
+ ## When to Use
12
+
13
+ Use `/quarri-insights` when users need:
14
+ - Statistical analysis: "What's the distribution of order values?"
15
+ - Business interpretation: "What insights can you give me from this data?"
16
+ - Correlation analysis: "Is there a relationship between price and quantity?"
17
+ - Actionable recommendations: "What should we do based on these numbers?"
18
+
19
+ ## Part 1: Statistical Analysis
20
+
21
+ ### Analysis Types
22
+
23
+ #### 1. Descriptive Statistics
24
+
25
+ For numeric columns, calculate:
26
+ - **Central tendency**: mean, median, mode
27
+ - **Spread**: std, variance, range, IQR
28
+ - **Shape**: skewness, kurtosis
29
+ - **Percentiles**: 25th, 50th, 75th, 90th, 95th, 99th
30
+
31
+ ```python
32
+ import pandas as pd
33
+ import numpy as np
34
+
35
+ def descriptive_stats(df, column):
36
+ return {
37
+ 'count': df[column].count(),
38
+ 'mean': df[column].mean(),
39
+ 'median': df[column].median(),
40
+ 'std': df[column].std(),
41
+ 'min': df[column].min(),
42
+ 'max': df[column].max(),
43
+ 'q25': df[column].quantile(0.25),
44
+ 'q75': df[column].quantile(0.75),
45
+ 'skew': df[column].skew(),
46
+ 'kurtosis': df[column].kurtosis()
47
+ }
48
+ ```
49
+
50
+ #### 2. Distribution Analysis
51
+
52
+ Analyze how values are distributed:
53
+ - **Histogram bins**: Frequency distribution
54
+ - **Normality test**: Shapiro-Wilk or D'Agostino
55
+ - **Distribution fit**: Best-fit distribution type
56
+
57
+ ```python
58
+ from scipy import stats
59
+
60
+ def distribution_analysis(df, column):
61
+ data = df[column].dropna()
62
+ hist, bin_edges = np.histogram(data, bins='auto')
63
+
64
+ if len(data) >= 20:
65
+ stat, p_value = stats.shapiro(data[:5000])
66
+ is_normal = p_value > 0.05
67
+ else:
68
+ is_normal = None
69
+ p_value = None
70
+
71
+ return {
72
+ 'histogram': {'counts': hist.tolist(), 'edges': bin_edges.tolist()},
73
+ 'is_normal': is_normal,
74
+ 'normality_p_value': p_value
75
+ }
76
+ ```
77
+
78
+ #### 3. Correlation Analysis
79
+
80
+ Find relationships between numeric columns:
81
+ - **Pearson correlation**: Linear relationships
82
+ - **Spearman correlation**: Monotonic relationships
83
+ - **Strong correlations**: |r| > 0.5
84
+
85
+ ```python
86
+ def correlation_analysis(df, columns):
87
+ numeric_df = df[columns].select_dtypes(include=[np.number])
88
+ pearson = numeric_df.corr(method='pearson')
89
+ spearman = numeric_df.corr(method='spearman')
90
+
91
+ strong_correlations = []
92
+ for i, col1 in enumerate(numeric_df.columns):
93
+ for j, col2 in enumerate(numeric_df.columns):
94
+ if i < j:
95
+ r = pearson.loc[col1, col2]
96
+ if abs(r) > 0.5:
97
+ strong_correlations.append({
98
+ 'columns': [col1, col2],
99
+ 'pearson_r': r,
100
+ 'spearman_r': spearman.loc[col1, col2]
101
+ })
102
+
103
+ return {
104
+ 'correlation_matrix': pearson.to_dict(),
105
+ 'strong_correlations': strong_correlations
106
+ }
107
+ ```
108
+
109
+ #### 4. Outlier Detection
110
+
111
+ Identify unusual values:
112
+ - **Z-score method**: Values > 3 std from mean
113
+ - **IQR method**: Values outside 1.5*IQR from quartiles
114
+
115
+ ```python
116
+ def detect_outliers(df, column, method='iqr'):
117
+ data = df[column].dropna()
118
+
119
+ if method == 'zscore':
120
+ z_scores = np.abs(stats.zscore(data))
121
+ outliers = data[z_scores > 3]
122
+ elif method == 'iqr':
123
+ q1, q3 = data.quantile([0.25, 0.75])
124
+ iqr = q3 - q1
125
+ lower_bound = q1 - 1.5 * iqr
126
+ upper_bound = q3 + 1.5 * iqr
127
+ outliers = data[(data < lower_bound) | (data > upper_bound)]
128
+
129
+ return {
130
+ 'outlier_count': len(outliers),
131
+ 'outlier_percentage': len(outliers) / len(data) * 100,
132
+ 'outlier_values': outliers.head(20).tolist(),
133
+ 'bounds': {'lower': lower_bound, 'upper': upper_bound} if method == 'iqr' else None
134
+ }
135
+ ```
136
+
137
+ #### 5. Time Series Analysis
138
+
139
+ For time-based data:
140
+ - **Trend detection**: Linear regression on time
141
+ - **Growth rate**: Period-over-period changes
142
+ - **Volatility**: Coefficient of variation
143
+
144
+ ```python
145
+ def time_series_analysis(df, date_column, value_column):
146
+ df_sorted = df.sort_values(date_column)
147
+ df_sorted['pct_change'] = df_sorted[value_column].pct_change()
148
+
149
+ x = np.arange(len(df_sorted))
150
+ slope, intercept, r_value, p_value, std_err = stats.linregress(x, df_sorted[value_column])
151
+
152
+ trend_direction = 'increasing' if slope > 0 else 'decreasing' if slope < 0 else 'stable'
153
+
154
+ return {
155
+ 'trend_direction': trend_direction,
156
+ 'trend_slope': slope,
157
+ 'trend_r_squared': r_value ** 2,
158
+ 'average_growth_rate': df_sorted['pct_change'].mean(),
159
+ 'volatility': df_sorted[value_column].std() / df_sorted[value_column].mean()
160
+ }
161
+ ```
162
+
163
+ #### 6. Segment Comparison
164
+
165
+ Compare groups within data:
166
+ - **Group statistics**: Mean, median by group
167
+ - **Statistical tests**: t-test, ANOVA for differences
168
+ - **Effect size**: Cohen's d for magnitude
169
+
170
+ ```python
171
+ def segment_comparison(df, group_column, value_column):
172
+ groups = df.groupby(group_column)[value_column]
173
+ group_stats = groups.agg(['count', 'mean', 'median', 'std']).to_dict('index')
174
+
175
+ group_values = [group.values for name, group in groups]
176
+ if len(group_values) >= 2:
177
+ f_stat, p_value = stats.f_oneway(*group_values)
178
+ significant_difference = p_value < 0.05
179
+ else:
180
+ f_stat, p_value = None, None
181
+ significant_difference = None
182
+
183
+ return {
184
+ 'group_statistics': group_stats,
185
+ 'anova_f_statistic': f_stat,
186
+ 'anova_p_value': p_value,
187
+ 'significant_difference': significant_difference
188
+ }
189
+ ```
190
+
191
+ ## Part 2: Business Insight Generation
192
+
193
+ ### Pattern Recognition
194
+
195
+ Identify these patterns in the data:
196
+
197
+ **Trends**
198
+ - Is the metric growing, declining, or stable?
199
+ - What's the rate of change?
200
+ - Are there inflection points?
201
+
202
+ **Concentrations**
203
+ - Does a small portion drive most results? (Pareto principle)
204
+ - Are there dominant segments?
205
+
206
+ **Anomalies**
207
+ - Are there outliers?
208
+ - Are there unexpected values?
209
+ - Are there gaps or missing patterns?
210
+
211
+ **Relationships**
212
+ - Do variables correlate?
213
+ - Are there surprising connections?
214
+ - What drives what?
215
+
216
+ ### Insight Categories
217
+
218
+ #### Key Finding
219
+ The single most important takeaway:
220
+ > "Electronics drives 68% of total revenue but represents only 25% of product categories."
221
+
222
+ #### Performance Insights
223
+ How things are performing:
224
+ > "Revenue grew 23% YoY, outpacing the industry average of 15%."
225
+
226
+ #### Comparison Insights
227
+ How segments differ:
228
+ > "Enterprise customers spend 4.2x more per order than SMB customers."
229
+
230
+ #### Trend Insights
231
+ What's changing over time:
232
+ > "Mobile orders increased from 12% to 47% of total orders over 18 months."
233
+
234
+ #### Risk Insights
235
+ Warning signs and concerns:
236
+ > "Three of top 10 customers reduced orders by >50% this quarter."
237
+
238
+ #### Opportunity Insights
239
+ Potential for growth or improvement:
240
+ > "Cross-sell rate for Product A is only 8%, compared to 28% category average."
241
+
242
+ ### Insight Quality Criteria
243
+
244
+ Good insights are:
245
+
246
+ **Specific**: Include actual numbers
247
+ - Bad: "Revenue increased"
248
+ - Good: "Revenue increased 23% from $4.2M to $5.2M"
249
+
250
+ **Contextual**: Provide comparison points
251
+ - Bad: "We have 1,200 customers"
252
+ - Good: "Customer count grew 15% to 1,200, vs. 8% industry average"
253
+
254
+ **Actionable**: Suggest what to do
255
+ - Bad: "Conversion rate varies by channel"
256
+ - Good: "Email conversion is 2.3x higher than social - consider reallocating ad spend"
257
+
258
+ **Relevant**: Connect to business goals
259
+ - Bad: "The median is 45"
260
+ - Good: "Half of orders are under $45, suggesting opportunity for upselling"
261
+
262
+ ## Workflow
263
+
264
+ 1. **Receive data**: From a previous query or via `quarri_execute_sql`
265
+ 2. **Identify analysis type**: Based on data shape and user question
266
+ 3. **Perform statistical analysis**: Run appropriate calculations
267
+ 4. **Generate insights**: Interpret results in business context
268
+ 5. **Prioritize findings**: Rank by impact, actionability, urgency
269
+ 6. **Frame recommendations**: Suggest specific actions
270
+
271
+ ## Output Format
272
+
273
+ ```markdown
274
+ ## Analysis: [Data Description]
275
+
276
+ ### Data Overview
277
+ - Rows: [count]
278
+ - Numeric columns: [list]
279
+ - Categorical columns: [list]
280
+ - Date range: [if applicable]
281
+
282
+ ### Statistical Findings
283
+
284
+ #### Descriptive Statistics
285
+ | Metric | Value |
286
+ |--------|-------|
287
+ | Mean | X |
288
+ | Median | Y |
289
+ | Std | Z |
290
+
291
+ #### Key Patterns
292
+ - [Pattern 1 with numbers]
293
+ - [Pattern 2 with numbers]
294
+ - [Pattern 3 with numbers]
295
+
296
+ ### Business Insights
297
+
298
+ #### Key Finding
299
+ [The single most important insight - bolded and specific]
300
+
301
+ #### Insights
302
+
303
+ **1. [Category]: [Insight Title]**
304
+ [Specific insight with numbers]
305
+ - **Implication**: [What this means]
306
+ - **Recommended Action**: [What to do]
307
+
308
+ **2. [Category]: [Insight Title]**
309
+ [Specific insight with numbers]
310
+ - **Implication**: [What this means]
311
+ - **Recommended Action**: [What to do]
312
+
313
+ ### Risks to Monitor
314
+ - [Risk 1 with trigger condition]
315
+ - [Risk 2 with trigger condition]
316
+
317
+ ### Recommended Next Steps
318
+ 1. [Action 1]
319
+ 2. [Action 2]
320
+ 3. [Suggested follow-up analysis]
321
+ ```
322
+
323
+ ## Integration
324
+
325
+ This skill works well with:
326
+ - `/quarri-query`: Get data first, then analyze
327
+ - `/quarri-chart`: Visualize statistical findings
328
+ - `/quarri-analyze`: Called as part of the full analysis pipeline
@@ -0,0 +1,400 @@
1
+ ---
2
+ description: Define business metrics and build metric trees for KPI decomposition
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # /quarri-metric - Metric Definition & Metric Trees
8
+
9
+ Define new business metrics and build metric trees that decompose KPIs into component drivers for root cause analysis.
10
+
11
+ ## When to Use
12
+
13
+ Use `/quarri-metric` when users want to:
14
+ - Create metrics: "Create a metric for customer lifetime value"
15
+ - Define KPIs: "Define a retention rate metric"
16
+ - Build metric trees: "Decompose revenue into its drivers"
17
+ - Understand relationships: "What metrics drive conversion rate?"
18
+
19
+ ## Part 1: Metric Definition
20
+
21
+ ### Step 1: Understand the Metric
22
+
23
+ Gather these details through conversation:
24
+
25
+ 1. **Name**: What should this metric be called?
26
+ - Use clear, business-friendly names
27
+ - Examples: "Monthly Recurring Revenue", "Customer Churn Rate"
28
+
29
+ 2. **Description**: What does it measure and why is it important?
30
+
31
+ 3. **Calculation**: How is it computed?
32
+ - What's the formula?
33
+ - What columns are involved?
34
+
35
+ 4. **Dimensions**: How can it be broken down?
36
+ - By region, product, customer segment?
37
+ - Time granularity (daily, monthly, yearly)?
38
+
39
+ 5. **Synonyms**: What else might users call this?
40
+ - "MRR" for "Monthly Recurring Revenue"
41
+ - "AOV" for "Average Order Value"
42
+
43
+ ### Step 2: Map to Schema
44
+
45
+ 1. Fetch schema using `quarri_get_schema`
46
+ 2. Identify relevant tables and columns
47
+ 3. Validate column names and types
48
+
49
+ ### Step 3: Write SQL Template
50
+
51
+ ```sql
52
+ -- Template with placeholders for dimensions
53
+ SELECT
54
+ {dimension_columns},
55
+ SUM(order_total) / COUNT(DISTINCT customer_id) as average_order_value
56
+ FROM quarri.bridge
57
+ WHERE {filter_conditions}
58
+ GROUP BY {dimension_columns}
59
+ ```
60
+
61
+ ### Step 4: Save
62
+
63
+ Create the metric using `quarri_create_metric`:
64
+ ```json
65
+ {
66
+ "name": "Average Order Value",
67
+ "description": "Average revenue per order",
68
+ "sql_template": "SELECT SUM(order_total) / COUNT(*) as aov FROM quarri.bridge",
69
+ "dimensions": ["region", "product_category", "month"]
70
+ }
71
+ ```
72
+
73
+ ## Part 2: Metric Trees
74
+
75
+ Metric trees decompose a top-level KPI into its component drivers, enabling systematic root cause analysis.
76
+
77
+ ### What is a Metric Tree?
78
+
79
+ A metric tree shows how a high-level metric breaks down into component parts:
80
+
81
+ ```
82
+ Revenue
83
+ ├── = Customers × Orders/Customer × Revenue/Order
84
+
85
+ ├── Customers
86
+ │ ├── New Customers (acquisition)
87
+ │ └── Returning Customers (retention)
88
+
89
+ ├── Orders per Customer (frequency)
90
+ │ ├── Purchase occasions
91
+ │ └── Repeat purchase rate
92
+
93
+ └── Revenue per Order (basket size)
94
+ ├── Units per order
95
+ ├── Price per unit
96
+ └── Discount rate
97
+ ```
98
+
99
+ ### Common Metric Tree Patterns
100
+
101
+ #### E-Commerce Revenue Tree
102
+ ```
103
+ Revenue = Traffic × Conversion Rate × Average Order Value
104
+
105
+ ├── Traffic
106
+ │ ├── Organic (SEO, direct)
107
+ │ ├── Paid (ads, affiliates)
108
+ │ └── Referral (social, email)
109
+
110
+ ├── Conversion Rate
111
+ │ ├── Add-to-cart rate
112
+ │ ├── Cart-to-checkout rate
113
+ │ └── Checkout completion rate
114
+
115
+ └── Average Order Value
116
+ ├── Items per order
117
+ └── Price per item
118
+ ```
119
+
120
+ #### SaaS Revenue Tree
121
+ ```
122
+ MRR = Customers × ARPU
123
+
124
+ ├── Customers
125
+ │ ├── New MRR (new customers)
126
+ │ ├── Expansion MRR (upgrades)
127
+ │ ├── Contraction MRR (downgrades)
128
+ │ └── Churned MRR (cancellations)
129
+
130
+ └── ARPU (Average Revenue Per User)
131
+ ├── Plan mix
132
+ ├── Add-on adoption
133
+ └── Usage-based fees
134
+ ```
135
+
136
+ #### Customer Lifetime Value Tree
137
+ ```
138
+ CLV = ARPU × Avg Lifetime × Gross Margin
139
+
140
+ ├── ARPU (Average Revenue Per User)
141
+ │ ├── Base subscription
142
+ │ └── Additional services
143
+
144
+ ├── Average Customer Lifetime
145
+ │ ├── 1 / Churn Rate
146
+ │ └── Retention by cohort
147
+
148
+ └── Gross Margin
149
+ ├── Revenue
150
+ └── Cost of goods/service
151
+ ```
152
+
153
+ #### Sales Pipeline Tree
154
+ ```
155
+ Revenue = Leads × Conversion Rate × Deal Size
156
+
157
+ ├── Leads
158
+ │ ├── Marketing Qualified (MQL)
159
+ │ ├── Sales Qualified (SQL)
160
+ │ └── Opportunity Created
161
+
162
+ ├── Conversion Rate
163
+ │ ├── MQL → SQL rate
164
+ │ ├── SQL → Opportunity rate
165
+ │ ├── Opportunity → Proposal rate
166
+ │ └── Proposal → Close rate
167
+
168
+ └── Deal Size
169
+ ├── Contract value
170
+ ├── Upsell/cross-sell
171
+ └── Discounting
172
+ ```
173
+
174
+ ### Building a Metric Tree
175
+
176
+ #### Step 1: Identify the Top-Level Metric
177
+ - What KPI are you trying to understand or improve?
178
+ - Example: "Revenue", "Conversion Rate", "Retention"
179
+
180
+ #### Step 2: Find the Mathematical Relationship
181
+ Express the metric as a formula:
182
+ - **Multiplicative**: Revenue = Customers × ARPU
183
+ - **Additive**: Revenue = Product A + Product B + Product C
184
+ - **Ratio**: Conversion = Conversions / Visitors
185
+
186
+ #### Step 3: Decompose Each Component
187
+ For each component, ask: "What drives this?"
188
+ - Keep decomposing until you reach actionable metrics
189
+ - Stop when you reach metrics you can directly measure and influence
190
+
191
+ #### Step 4: Validate the Tree
192
+ - Components should be MECE (mutually exclusive, collectively exhaustive)
193
+ - Math should work: components should sum/multiply to parent
194
+ - Each leaf should be measurable in your data
195
+
196
+ ### Using Metric Trees for Analysis
197
+
198
+ Once you have a metric tree, use it for:
199
+
200
+ **1. Performance Attribution**
201
+ When a metric changes, quantify how much each driver contributed:
202
+ ```
203
+ Revenue dropped 10% ($100K → $90K)
204
+
205
+ Attribution:
206
+ ├── Customer count: -5% impact ($5K)
207
+ ├── Order frequency: -3% impact ($3K)
208
+ └── Average order value: -2% impact ($2K)
209
+ ```
210
+
211
+ **2. Root Cause Analysis**
212
+ Drill into the largest impact driver:
213
+ ```
214
+ Customer count dropped 5%
215
+ ├── New customers: -8% (PRIMARY CAUSE)
216
+ │ └── Paid acquisition: -15%
217
+ │ └── Organic: +2%
218
+ └── Retention: +3%
219
+ ```
220
+
221
+ **3. Opportunity Sizing**
222
+ Identify highest-leverage improvements:
223
+ ```
224
+ If we improve conversion rate by 10%:
225
+ ├── Current: 2.5% conversion
226
+ ├── Target: 2.75% conversion
227
+ └── Revenue impact: +$50K/month
228
+ ```
229
+
230
+ ### SQL for Metric Tree Analysis
231
+
232
+ Generate SQL that calculates all components of a metric tree:
233
+
234
+ ```sql
235
+ -- Revenue metric tree components
236
+ WITH metrics AS (
237
+ SELECT
238
+ period,
239
+ COUNT(DISTINCT customer_id) as customers,
240
+ COUNT(*) as orders,
241
+ SUM(revenue) as revenue,
242
+ -- Derived metrics
243
+ COUNT(*)::float / COUNT(DISTINCT customer_id) as orders_per_customer,
244
+ SUM(revenue)::float / COUNT(*) as revenue_per_order
245
+ FROM quarri.bridge
246
+ WHERE order_date >= DATE '2024-01-01'
247
+ GROUP BY period
248
+ )
249
+ SELECT
250
+ period,
251
+ customers,
252
+ orders_per_customer,
253
+ revenue_per_order,
254
+ revenue,
255
+ -- Verify: customers * orders_per_customer * revenue_per_order ≈ revenue
256
+ customers * orders_per_customer * revenue_per_order as calculated_revenue
257
+ FROM metrics
258
+ ORDER BY period;
259
+ ```
260
+
261
+ ### Period-over-Period Comparison
262
+
263
+ ```sql
264
+ -- Compare current vs previous period for root cause analysis
265
+ WITH current_period AS (
266
+ SELECT
267
+ COUNT(DISTINCT customer_id) as customers,
268
+ COUNT(*)::float / COUNT(DISTINCT customer_id) as frequency,
269
+ SUM(revenue)::float / COUNT(*) as aov,
270
+ SUM(revenue) as revenue
271
+ FROM quarri.bridge
272
+ WHERE order_date >= DATE '2024-12-01'
273
+ ),
274
+ previous_period AS (
275
+ SELECT
276
+ COUNT(DISTINCT customer_id) as customers,
277
+ COUNT(*)::float / COUNT(DISTINCT customer_id) as frequency,
278
+ SUM(revenue)::float / COUNT(*) as aov,
279
+ SUM(revenue) as revenue
280
+ FROM quarri.bridge
281
+ WHERE order_date >= DATE '2024-11-01' AND order_date < DATE '2024-12-01'
282
+ )
283
+ SELECT
284
+ 'Customers' as metric,
285
+ p.customers as previous,
286
+ c.customers as current,
287
+ (c.customers - p.customers)::float / p.customers * 100 as pct_change
288
+ FROM current_period c, previous_period p
289
+ UNION ALL
290
+ SELECT
291
+ 'Frequency' as metric,
292
+ p.frequency as previous,
293
+ c.frequency as current,
294
+ (c.frequency - p.frequency)::float / p.frequency * 100 as pct_change
295
+ FROM current_period c, previous_period p
296
+ -- ... continue for all components
297
+ ```
298
+
299
+ ## Common Metric Patterns
300
+
301
+ ### Simple Aggregation
302
+ ```sql
303
+ -- Total Revenue
304
+ SELECT SUM(revenue) as total_revenue FROM quarri.bridge
305
+
306
+ -- Order Count
307
+ SELECT COUNT(*) as order_count FROM quarri.bridge
308
+ ```
309
+
310
+ ### Ratio Metrics
311
+ ```sql
312
+ -- Conversion Rate
313
+ SELECT
314
+ COUNT(CASE WHEN status = 'completed' THEN 1 END)::float /
315
+ COUNT(*) as conversion_rate
316
+ FROM orders
317
+
318
+ -- Gross Margin
319
+ SELECT
320
+ (SUM(revenue) - SUM(cost)) / SUM(revenue) as gross_margin
321
+ FROM quarri.bridge
322
+ ```
323
+
324
+ ### Time-Based Metrics
325
+ ```sql
326
+ -- Monthly Recurring Revenue
327
+ SELECT
328
+ DATE_TRUNC('month', subscription_date) as month,
329
+ SUM(monthly_amount) as mrr
330
+ FROM subscriptions
331
+ WHERE status = 'active'
332
+ GROUP BY month
333
+
334
+ -- Year-over-Year Growth
335
+ SELECT
336
+ current.period,
337
+ (current.revenue - previous.revenue) / previous.revenue as yoy_growth
338
+ FROM (...) current
339
+ JOIN (...) previous ON current.period = previous.period + INTERVAL '1 year'
340
+ ```
341
+
342
+ ### Customer Metrics
343
+ ```sql
344
+ -- Customer Lifetime Value
345
+ SELECT
346
+ customer_id,
347
+ SUM(order_total) as lifetime_value,
348
+ COUNT(*) as order_count,
349
+ MIN(order_date) as first_order,
350
+ MAX(order_date) as last_order
351
+ FROM orders
352
+ GROUP BY customer_id
353
+ ```
354
+
355
+ ## Output Format
356
+
357
+ ```markdown
358
+ ## Metric Definition: [Metric Name]
359
+
360
+ ### Summary
361
+ **Name**: [Metric Name]
362
+ **Description**: [What it measures]
363
+ **Synonyms**: [Alternative names]
364
+
365
+ ### Calculation
366
+ [Plain English explanation of the formula]
367
+
368
+ ### SQL Template
369
+ ```sql
370
+ [SQL code]
371
+ ```
372
+
373
+ ### Dimensions
374
+ - [Dimension 1]: [Description]
375
+ - [Dimension 2]: [Description]
376
+
377
+ ### Metric Tree (if applicable)
378
+ ```
379
+ [Top-level metric]
380
+ ├── [Component 1]
381
+ │ ├── [Sub-component 1a]
382
+ │ └── [Sub-component 1b]
383
+ ├── [Component 2]
384
+ └── [Component 3]
385
+ ```
386
+
387
+ ### Validation Results
388
+ - Query executed successfully
389
+ - Sample result: [Sample value]
390
+
391
+ ### Status
392
+ [Ready to save / Needs revision]
393
+ ```
394
+
395
+ ## Integration
396
+
397
+ After creating a metric:
398
+ - Use with `/quarri-query` for natural language queries
399
+ - Reference in `/quarri-analyze` for comprehensive analysis
400
+ - Use `/quarri-diagnose` for root cause analysis with metric trees