@duckcodeailabs/dql-cli 0.3.0 → 0.5.0
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.
- package/dist/assets/dql-notebook/assets/index-C7bfa1Fe.js +477 -0
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/assets/templates/dql.config.reference.json +154 -0
- package/dist/assets/templates/ecommerce/dql.config.json +5 -0
- package/dist/assets/templates/ecommerce/semantic-layer/cubes/customers_cube.yaml +49 -0
- package/dist/assets/templates/ecommerce/semantic-layer/cubes/orders_cube.yaml +70 -0
- package/dist/assets/templates/ecommerce/semantic-layer/dimensions/channel.yaml +5 -1
- package/dist/assets/templates/ecommerce/semantic-layer/dimensions/order_date.yaml +9 -0
- package/dist/assets/templates/ecommerce/semantic-layer/dimensions/region.yaml +9 -0
- package/dist/assets/templates/ecommerce/semantic-layer/dimensions/segment.yaml +8 -0
- package/dist/assets/templates/ecommerce/semantic-layer/hierarchies/customer_geo.yaml +18 -0
- package/dist/assets/templates/ecommerce/semantic-layer/metrics/avg_order_value.yaml +10 -0
- package/dist/assets/templates/ecommerce/semantic-layer/metrics/gmv.yaml +7 -1
- package/dist/assets/templates/ecommerce/semantic-layer/metrics/gross_margin.yaml +10 -0
- package/dist/assets/templates/ecommerce/semantic-layer/metrics/order_count.yaml +10 -0
- package/dist/assets/templates/saas/dql.config.json +5 -0
- package/dist/assets/templates/saas/semantic-layer/dimensions/owner_segment.yaml +8 -0
- package/dist/assets/templates/saas/semantic-layer/dimensions/plan_tier.yaml +8 -0
- package/dist/assets/templates/saas/semantic-layer/dimensions/risk_bucket.yaml +9 -0
- package/dist/assets/templates/saas/semantic-layer/dimensions/status.yaml +8 -0
- package/dist/assets/templates/saas/semantic-layer/hierarchies/account_segments.yaml +18 -0
- package/dist/assets/templates/saas/semantic-layer/metrics/account_count.yaml +10 -0
- package/dist/assets/templates/saas/semantic-layer/metrics/expansion_mrr.yaml +11 -0
- package/dist/assets/templates/saas/semantic-layer/metrics/mrr.yaml +7 -1
- package/dist/assets/templates/starter/dql.config.json +5 -0
- package/dist/assets/templates/starter/notebooks/semantic_layer_tutorial.dqlnb +60 -0
- package/dist/assets/templates/starter/semantic-layer/cubes/revenue_cube.yaml +77 -0
- package/dist/assets/templates/starter/semantic-layer/dimensions/segment_tier.yaml +1 -1
- package/dist/assets/templates/starter/semantic-layer/metrics/revenue.yaml +1 -1
- package/dist/assets/templates/taxi/dql.config.json +5 -0
- package/dist/assets/templates/taxi/semantic-layer/dimensions/airport_flag.yaml +8 -0
- package/dist/assets/templates/taxi/semantic-layer/dimensions/dropoff_borough.yaml +9 -0
- package/dist/assets/templates/taxi/semantic-layer/dimensions/payment_type.yaml +8 -0
- package/dist/assets/templates/taxi/semantic-layer/dimensions/pickup_borough.yaml +9 -0
- package/dist/assets/templates/taxi/semantic-layer/dimensions/pickup_date.yaml +9 -0
- package/dist/assets/templates/taxi/semantic-layer/hierarchies/trip_route.yaml +14 -0
- package/dist/assets/templates/taxi/semantic-layer/metrics/avg_trip_miles.yaml +10 -0
- package/dist/assets/templates/taxi/semantic-layer/metrics/total_fare.yaml +10 -0
- package/dist/assets/templates/taxi/semantic-layer/metrics/total_tips.yaml +10 -0
- package/dist/assets/templates/taxi/semantic-layer/metrics/trip_count.yaml +10 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +36 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +8 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/semantic.d.ts +10 -0
- package/dist/commands/semantic.d.ts.map +1 -0
- package/dist/commands/semantic.js +242 -0
- package/dist/commands/semantic.js.map +1 -0
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/local-runtime.d.ts +2 -0
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +106 -18
- package/dist/local-runtime.js.map +1 -1
- package/dist/package.json +44 -0
- package/package.json +15 -14
- package/LICENSE +0 -123
- package/dist/assets/dql-notebook/assets/index-_N_gerXe.js +0 -353
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-C7bfa1Fe.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/react-CRB3T2We.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/codemirror-CCrEt63p.js">
|
|
13
13
|
</head>
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "DQL Config Reference — copy sections you need into your dql.config.json",
|
|
3
|
+
|
|
4
|
+
"project": "my-project-name",
|
|
5
|
+
|
|
6
|
+
"_comment_connections": "=== CONNECTION OPTIONS ===",
|
|
7
|
+
|
|
8
|
+
"_option_1_duckdb_memory": {
|
|
9
|
+
"defaultConnection": {
|
|
10
|
+
"driver": "file",
|
|
11
|
+
"filepath": ":memory:"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
"_option_2_duckdb_file": {
|
|
16
|
+
"defaultConnection": {
|
|
17
|
+
"driver": "duckdb",
|
|
18
|
+
"filepath": "./data/warehouse.duckdb"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
"_option_3_snowflake": {
|
|
23
|
+
"defaultConnection": {
|
|
24
|
+
"driver": "snowflake",
|
|
25
|
+
"account": "your-account.snowflakecomputing.com",
|
|
26
|
+
"username": "your_user",
|
|
27
|
+
"password": "${SNOWFLAKE_PASSWORD}",
|
|
28
|
+
"database": "ANALYTICS",
|
|
29
|
+
"schema": "PUBLIC",
|
|
30
|
+
"warehouse": "COMPUTE_WH",
|
|
31
|
+
"role": "ANALYST"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
"_option_4_bigquery": {
|
|
36
|
+
"defaultConnection": {
|
|
37
|
+
"driver": "bigquery",
|
|
38
|
+
"project": "your-gcp-project-id",
|
|
39
|
+
"dataset": "analytics",
|
|
40
|
+
"keyFilename": "./service-account.json"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
"_option_5_postgres": {
|
|
45
|
+
"defaultConnection": {
|
|
46
|
+
"driver": "postgres",
|
|
47
|
+
"host": "localhost",
|
|
48
|
+
"port": 5432,
|
|
49
|
+
"database": "analytics",
|
|
50
|
+
"username": "your_user",
|
|
51
|
+
"password": "${POSTGRES_PASSWORD}"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
"_option_6_sqlite": {
|
|
56
|
+
"defaultConnection": {
|
|
57
|
+
"driver": "sqlite",
|
|
58
|
+
"database": "./data/analytics.sqlite"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
"_comment_semantic": "=== SEMANTIC LAYER OPTIONS ===",
|
|
63
|
+
|
|
64
|
+
"_semantic_option_1_dql_native": {
|
|
65
|
+
"semanticLayer": {
|
|
66
|
+
"provider": "dql"
|
|
67
|
+
},
|
|
68
|
+
"_directory_structure": {
|
|
69
|
+
"semantic-layer/metrics/": "one YAML file per metric",
|
|
70
|
+
"semantic-layer/dimensions/": "one YAML file per dimension",
|
|
71
|
+
"semantic-layer/hierarchies/":"one YAML file per hierarchy",
|
|
72
|
+
"semantic-layer/cubes/": "one YAML file per cube (groups measures + dimensions + joins)"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
"_semantic_option_2_dql_custom_path": {
|
|
77
|
+
"semanticLayer": {
|
|
78
|
+
"provider": "dql",
|
|
79
|
+
"path": "./my-definitions"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
"_semantic_option_3_dbt": {
|
|
84
|
+
"semanticLayer": {
|
|
85
|
+
"provider": "dbt",
|
|
86
|
+
"projectPath": "/absolute/path/to/your/dbt-project"
|
|
87
|
+
},
|
|
88
|
+
"_notes": {
|
|
89
|
+
"how_it_works": "Reads semantic_models and metrics from your dbt models/**/*.yml files",
|
|
90
|
+
"requires": "dbt 1.6+ with semantic_models defined in YAML",
|
|
91
|
+
"relative_path": "You can also use a relative path: ../my-dbt-repo"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
"_semantic_option_4_cubejs": {
|
|
96
|
+
"semanticLayer": {
|
|
97
|
+
"provider": "cubejs",
|
|
98
|
+
"projectPath": "/absolute/path/to/your/cube-project"
|
|
99
|
+
},
|
|
100
|
+
"_notes": {
|
|
101
|
+
"how_it_works": "Reads cube definitions from model/ or schema/ directory",
|
|
102
|
+
"relative_path": "You can also use a relative path: ../my-cube-project"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
"_semantic_option_5_dbt_remote_github": {
|
|
107
|
+
"semanticLayer": {
|
|
108
|
+
"provider": "dbt",
|
|
109
|
+
"source": "github",
|
|
110
|
+
"repoUrl": "https://github.com/your-org/dbt-metrics.git",
|
|
111
|
+
"branch": "main",
|
|
112
|
+
"subPath": "models"
|
|
113
|
+
},
|
|
114
|
+
"_notes": {
|
|
115
|
+
"how_it_works": "Clones the remote repo into ~/.dql/cache/repos/ and reads dbt semantic models from it",
|
|
116
|
+
"auth": "For private repos, set GITHUB_TOKEN environment variable",
|
|
117
|
+
"cache": "Cached for 10 minutes; use 'dql semantic pull' to force refresh"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
"_semantic_option_6_cubejs_remote_gitlab": {
|
|
122
|
+
"semanticLayer": {
|
|
123
|
+
"provider": "cubejs",
|
|
124
|
+
"source": "gitlab",
|
|
125
|
+
"repoUrl": "https://gitlab.com/your-org/cube-schema.git",
|
|
126
|
+
"branch": "main",
|
|
127
|
+
"subPath": ""
|
|
128
|
+
},
|
|
129
|
+
"_notes": {
|
|
130
|
+
"auth": "For private repos, set GITLAB_TOKEN environment variable"
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
"_semantic_option_7_snowflake": {
|
|
135
|
+
"semanticLayer": {
|
|
136
|
+
"provider": "snowflake",
|
|
137
|
+
"projectPath": "MY_DATABASE"
|
|
138
|
+
},
|
|
139
|
+
"_notes": {
|
|
140
|
+
"how_it_works": "Introspects Snowflake semantic views (SHOW SEMANTIC VIEWS) via the active connection",
|
|
141
|
+
"requires": "Snowflake account with semantic views (CREATE SEMANTIC VIEW) and a configured Snowflake connection",
|
|
142
|
+
"projectPath_usage": "Optional: filters semantic views to a specific database"
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
"_comment_preview": "=== PREVIEW / NOTEBOOK OPTIONS ===",
|
|
147
|
+
|
|
148
|
+
"dataDir": "./data",
|
|
149
|
+
"preview": {
|
|
150
|
+
"port": 3474,
|
|
151
|
+
"open": true,
|
|
152
|
+
"theme": "dark"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Customers cube — joinable from the orders cube.
|
|
2
|
+
|
|
3
|
+
name: customers
|
|
4
|
+
label: Customers Cube
|
|
5
|
+
description: Customer master data.
|
|
6
|
+
table: customers
|
|
7
|
+
domain: commerce
|
|
8
|
+
|
|
9
|
+
measures:
|
|
10
|
+
- name: customer_count
|
|
11
|
+
label: Customer Count
|
|
12
|
+
sql: COUNT(DISTINCT customer_id)
|
|
13
|
+
type: count_distinct
|
|
14
|
+
- name: avg_health_score
|
|
15
|
+
label: Average Health Score
|
|
16
|
+
sql: AVG(health_score)
|
|
17
|
+
type: avg
|
|
18
|
+
|
|
19
|
+
dimensions:
|
|
20
|
+
- name: customer_name
|
|
21
|
+
label: Customer Name
|
|
22
|
+
sql: customer_name
|
|
23
|
+
type: string
|
|
24
|
+
- name: segment
|
|
25
|
+
label: Segment
|
|
26
|
+
sql: segment
|
|
27
|
+
type: string
|
|
28
|
+
- name: region
|
|
29
|
+
label: Region
|
|
30
|
+
sql: region
|
|
31
|
+
type: string
|
|
32
|
+
- name: acquisition_channel
|
|
33
|
+
label: Acquisition Channel
|
|
34
|
+
sql: acquisition_channel
|
|
35
|
+
type: string
|
|
36
|
+
|
|
37
|
+
time_dimensions:
|
|
38
|
+
- name: first_order_date
|
|
39
|
+
label: First Order Date
|
|
40
|
+
sql: first_order_date
|
|
41
|
+
primary_time: true
|
|
42
|
+
granularities:
|
|
43
|
+
- month
|
|
44
|
+
- quarter
|
|
45
|
+
- year
|
|
46
|
+
|
|
47
|
+
tags:
|
|
48
|
+
- commerce
|
|
49
|
+
- customers
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Multi-table cube with joins — demonstrates cross-table semantic queries.
|
|
2
|
+
# This cube joins orders with customers to enable queries like:
|
|
3
|
+
# "total GMV by customer health_score and region"
|
|
4
|
+
|
|
5
|
+
name: orders
|
|
6
|
+
label: Orders Cube
|
|
7
|
+
description: E-commerce orders cube with customer join.
|
|
8
|
+
table: orders
|
|
9
|
+
domain: commerce
|
|
10
|
+
|
|
11
|
+
measures:
|
|
12
|
+
- name: gmv
|
|
13
|
+
label: Gross Merchandise Value
|
|
14
|
+
sql: SUM(order_total)
|
|
15
|
+
type: sum
|
|
16
|
+
- name: order_count
|
|
17
|
+
label: Order Count
|
|
18
|
+
sql: COUNT(order_id)
|
|
19
|
+
type: count
|
|
20
|
+
- name: avg_order_value
|
|
21
|
+
label: Average Order Value
|
|
22
|
+
sql: AVG(order_total)
|
|
23
|
+
type: avg
|
|
24
|
+
- name: avg_margin
|
|
25
|
+
label: Average Margin
|
|
26
|
+
sql: AVG(gross_margin)
|
|
27
|
+
type: avg
|
|
28
|
+
|
|
29
|
+
dimensions:
|
|
30
|
+
- name: segment
|
|
31
|
+
label: Segment
|
|
32
|
+
sql: segment
|
|
33
|
+
type: string
|
|
34
|
+
- name: channel
|
|
35
|
+
label: Channel
|
|
36
|
+
sql: channel
|
|
37
|
+
type: string
|
|
38
|
+
- name: region
|
|
39
|
+
label: Region
|
|
40
|
+
sql: region
|
|
41
|
+
type: string
|
|
42
|
+
- name: payment_method
|
|
43
|
+
label: Payment Method
|
|
44
|
+
sql: payment_method
|
|
45
|
+
type: string
|
|
46
|
+
- name: is_repeat
|
|
47
|
+
label: Repeat Customer
|
|
48
|
+
sql: is_repeat
|
|
49
|
+
type: boolean
|
|
50
|
+
|
|
51
|
+
time_dimensions:
|
|
52
|
+
- name: order_date
|
|
53
|
+
label: Order Date
|
|
54
|
+
sql: order_date
|
|
55
|
+
primary_time: true
|
|
56
|
+
granularities:
|
|
57
|
+
- day
|
|
58
|
+
- week
|
|
59
|
+
- month
|
|
60
|
+
- quarter
|
|
61
|
+
- year
|
|
62
|
+
|
|
63
|
+
joins:
|
|
64
|
+
- name: customers
|
|
65
|
+
type: left
|
|
66
|
+
sql: "${left}.customer_id = ${right}.customer_id"
|
|
67
|
+
|
|
68
|
+
tags:
|
|
69
|
+
- commerce
|
|
70
|
+
- ecommerce
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: customer_geo
|
|
2
|
+
label: Customer Geography
|
|
3
|
+
description: Drill from region down to customer segment.
|
|
4
|
+
domain: commerce
|
|
5
|
+
levels:
|
|
6
|
+
- name: region
|
|
7
|
+
label: Region
|
|
8
|
+
dimension: region
|
|
9
|
+
order: 1
|
|
10
|
+
- name: segment
|
|
11
|
+
label: Segment
|
|
12
|
+
dimension: segment
|
|
13
|
+
order: 2
|
|
14
|
+
- name: channel
|
|
15
|
+
label: Channel
|
|
16
|
+
dimension: channel
|
|
17
|
+
order: 3
|
|
18
|
+
defaultRollup: sum
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: account_segments
|
|
2
|
+
label: Account Segments
|
|
3
|
+
description: Drill from owner segment to plan tier to risk bucket.
|
|
4
|
+
domain: saas
|
|
5
|
+
levels:
|
|
6
|
+
- name: owner_segment
|
|
7
|
+
label: Owner Segment
|
|
8
|
+
dimension: owner_segment
|
|
9
|
+
order: 1
|
|
10
|
+
- name: plan_tier
|
|
11
|
+
label: Plan Tier
|
|
12
|
+
dimension: plan_tier
|
|
13
|
+
order: 2
|
|
14
|
+
- name: risk_bucket
|
|
15
|
+
label: Risk Bucket
|
|
16
|
+
dimension: risk_bucket
|
|
17
|
+
order: 3
|
|
18
|
+
defaultRollup: sum
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"title": "Semantic Layer Tutorial",
|
|
4
|
+
"cells": [
|
|
5
|
+
{
|
|
6
|
+
"id": "intro_1",
|
|
7
|
+
"type": "markdown",
|
|
8
|
+
"content": "# Semantic Layer Tutorial\n\nThis notebook walks you through setting up and using the DQL semantic layer.\n\nThe semantic layer lets you define **reusable metrics, dimensions, and hierarchies** in YAML files. Once defined, they appear in the sidebar panel and can be queried via the API.\n\n---\n\n## Prerequisites\n\nMake sure your `dql.config.json` has:\n\n```json\n\"semanticLayer\": {\n \"provider\": \"dql\"\n}\n```\n\nAnd you have YAML files in `semantic-layer/metrics/`, `semantic-layer/dimensions/`, etc."
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "check_1",
|
|
12
|
+
"type": "markdown",
|
|
13
|
+
"content": "## Step 1: Verify your data\n\nFirst, let's make sure you have data to work with. The starter template includes `data/revenue.csv`."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "query_1",
|
|
17
|
+
"type": "sql",
|
|
18
|
+
"name": "preview_data",
|
|
19
|
+
"content": "SELECT * FROM read_csv_auto('./data/revenue.csv') LIMIT 10"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "step2_md",
|
|
23
|
+
"type": "markdown",
|
|
24
|
+
"content": "## Step 2: Understand the YAML definitions\n\nYour `semantic-layer/` directory should contain:\n\n```\nsemantic-layer/\n├── metrics/\n│ └── revenue.yaml # SUM(amount) as total_revenue\n├── dimensions/\n│ └── segment_tier.yaml # segment_tier column\n├── hierarchies/\n│ └── revenue_time.yaml # fiscal_year → fiscal_quarter drill path\n└── cubes/\n └── revenue_cube.yaml # groups everything into one model\n```\n\n### Metric YAML format\n```yaml\nname: total_revenue\nlabel: Total Revenue\ndescription: Sum of recognized revenue\nsql: SUM(amount) # the SQL aggregate expression\ntype: sum # sum|count|count_distinct|avg|min|max\ntable: fct_revenue # which table this metric belongs to\ntags: [revenue, kpi]\n```\n\n### Dimension YAML format\n```yaml\nname: segment_tier\nlabel: Segment Tier\nsql: segment_tier # the column expression\ntype: string # string|number|date|boolean\ntable: fct_revenue\n```"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "step3_md",
|
|
28
|
+
"type": "markdown",
|
|
29
|
+
"content": "## Step 3: Query using semantic layer concepts\n\nYou can write SQL queries that use the same columns and aggregates defined in your semantic layer. The metric `total_revenue` is defined as `SUM(amount)` and the dimension `segment_tier` maps to the `segment_tier` column."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "query_2",
|
|
33
|
+
"type": "sql",
|
|
34
|
+
"name": "revenue_by_segment",
|
|
35
|
+
"content": "-- This query mirrors the semantic layer definitions:\n-- metric: total_revenue = SUM(amount)\n-- dimension: segment_tier\nSELECT\n segment_tier,\n SUM(amount) AS total_revenue,\n COUNT(*) AS deal_count,\n AVG(amount) AS avg_deal_size\nFROM read_csv_auto('./data/revenue.csv')\nGROUP BY segment_tier\nORDER BY total_revenue DESC"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "step4_md",
|
|
39
|
+
"type": "markdown",
|
|
40
|
+
"content": "## Step 4: Use hierarchies for drill-down\n\nThe `revenue_time` hierarchy defines a drill path: **fiscal_year → fiscal_quarter**.\n\nStart at the top level (year), then drill into quarters."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "query_3",
|
|
44
|
+
"type": "sql",
|
|
45
|
+
"name": "revenue_by_year",
|
|
46
|
+
"content": "-- Hierarchy level 1: fiscal_year\nSELECT\n fiscal_year,\n SUM(amount) AS total_revenue\nFROM read_csv_auto('./data/revenue.csv')\nGROUP BY fiscal_year\nORDER BY fiscal_year"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "query_4",
|
|
50
|
+
"type": "sql",
|
|
51
|
+
"name": "revenue_by_quarter",
|
|
52
|
+
"content": "-- Hierarchy level 2: drill into fiscal_quarter\nSELECT\n fiscal_year,\n fiscal_quarter,\n SUM(amount) AS total_revenue\nFROM read_csv_auto('./data/revenue.csv')\nGROUP BY fiscal_year, fiscal_quarter\nORDER BY fiscal_year, fiscal_quarter"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "step5_md",
|
|
56
|
+
"type": "markdown",
|
|
57
|
+
"content": "## Step 5: Explore in the sidebar\n\nClick the **Semantic Layer icon** (3rd icon in the left activity bar) to see:\n\n- **Metrics** — your defined aggregations with type badges (sum, count, avg...)\n- **Dimensions** — grouping columns with type indicators\n- **Hierarchies** — expandable drill paths\n\nYou can search and click any item to see its details.\n\n---\n\n## What's next?\n\n### Connect to dbt\nIf you have a dbt project with `semantic_models`, update `dql.config.json`:\n```json\n\"semanticLayer\": {\n \"provider\": \"dbt\",\n \"projectPath\": \"/path/to/your/dbt-project\"\n}\n```\n\n### Connect to Cube.js\n```json\n\"semanticLayer\": {\n \"provider\": \"cubejs\",\n \"projectPath\": \"/path/to/your/cube-project\"\n}\n```\n\n### Use cubes for multi-table models\nCreate `semantic-layer/cubes/my_cube.yaml` to define measures, dimensions, time dimensions, and joins all in one file. See the Reference panel (Help icon) for the full YAML format.\n\n### Full reference\nClick the **Help icon** (bottom of sidebar) → **Semantic Layer** and **Semantic Layer Providers** sections for complete YAML formats and config examples."
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Cube Definition — groups measures, dimensions, time dimensions, and joins
|
|
2
|
+
# into a single semantic model. This is the recommended way to define
|
|
3
|
+
# complex, multi-table semantic layers.
|
|
4
|
+
#
|
|
5
|
+
# The DQL notebook will automatically discover this cube and display
|
|
6
|
+
# its measures and dimensions in the Semantic Layer sidebar panel.
|
|
7
|
+
|
|
8
|
+
name: revenue
|
|
9
|
+
label: Revenue Cube
|
|
10
|
+
description: Core revenue analysis cube built on the starter revenue data.
|
|
11
|
+
table: read_csv_auto('./data/revenue.csv')
|
|
12
|
+
domain: revenue
|
|
13
|
+
owner: analytics-team
|
|
14
|
+
|
|
15
|
+
# Measures — aggregate calculations shown as "Metrics" in the UI
|
|
16
|
+
measures:
|
|
17
|
+
- name: total_revenue
|
|
18
|
+
label: Total Revenue
|
|
19
|
+
description: Sum of all recognized revenue.
|
|
20
|
+
sql: SUM(amount)
|
|
21
|
+
type: sum
|
|
22
|
+
tags:
|
|
23
|
+
- revenue
|
|
24
|
+
- kpi
|
|
25
|
+
|
|
26
|
+
- name: deal_count
|
|
27
|
+
label: Deal Count
|
|
28
|
+
description: Number of revenue deals.
|
|
29
|
+
sql: COUNT(*)
|
|
30
|
+
type: count
|
|
31
|
+
|
|
32
|
+
- name: avg_deal_size
|
|
33
|
+
label: Average Deal Size
|
|
34
|
+
description: Average revenue per deal.
|
|
35
|
+
sql: AVG(amount)
|
|
36
|
+
type: avg
|
|
37
|
+
tags:
|
|
38
|
+
- revenue
|
|
39
|
+
|
|
40
|
+
# Dimensions — grouping columns shown as "Dimensions" in the UI
|
|
41
|
+
dimensions:
|
|
42
|
+
- name: segment_tier
|
|
43
|
+
label: Segment Tier
|
|
44
|
+
description: Customer segment (Enterprise, Mid-Market, SMB).
|
|
45
|
+
sql: segment_tier
|
|
46
|
+
type: string
|
|
47
|
+
|
|
48
|
+
- name: fiscal_period
|
|
49
|
+
label: Fiscal Period
|
|
50
|
+
description: Fiscal period classification.
|
|
51
|
+
sql: fiscal_period
|
|
52
|
+
type: string
|
|
53
|
+
|
|
54
|
+
# Time Dimensions — date columns with granularity support (day/week/month/quarter/year)
|
|
55
|
+
time_dimensions:
|
|
56
|
+
- name: recognized_at
|
|
57
|
+
label: Recognition Date
|
|
58
|
+
description: Date revenue was recognized.
|
|
59
|
+
sql: recognized_at
|
|
60
|
+
primary_time: true
|
|
61
|
+
granularities:
|
|
62
|
+
- day
|
|
63
|
+
- week
|
|
64
|
+
- month
|
|
65
|
+
- quarter
|
|
66
|
+
- year
|
|
67
|
+
|
|
68
|
+
# Joins — connect this cube to other cubes for cross-table queries
|
|
69
|
+
# Example (uncomment if you have a customers cube):
|
|
70
|
+
# joins:
|
|
71
|
+
# - name: customers
|
|
72
|
+
# type: left
|
|
73
|
+
# sql: "${left}.customer_id = ${right}.id"
|
|
74
|
+
|
|
75
|
+
tags:
|
|
76
|
+
- revenue
|
|
77
|
+
- starter
|