Skip to content

Commit 83e0f0d

Browse files
committed
documentation
1 parent 18c7724 commit 83e0f0d

File tree

2 files changed

+181
-65
lines changed

2 files changed

+181
-65
lines changed

PBIX2VPAX.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Advanced Analysis Examples using pbix2vpax()
2+
3+
## Comparing Model Versions
4+
5+
**Track changes between model versions:**
6+
```sql
7+
WITH
8+
current_version AS (
9+
SELECT pbix2vpax('Sales_Model_v2.pbix') as analysis
10+
),
11+
previous_version AS (
12+
SELECT pbix2vpax('Sales_Model_v1.pbix') as analysis
13+
),
14+
current_measures AS (
15+
SELECT
16+
meas.MeasureName,
17+
meas.TableName,
18+
meas.MeasureExpression,
19+
meas.DataType
20+
FROM (SELECT UNNEST((SELECT analysis FROM current_version).Measures) as meas)
21+
),
22+
previous_measures AS (
23+
SELECT
24+
meas.MeasureName,
25+
meas.TableName,
26+
meas.MeasureExpression,
27+
meas.DataType
28+
FROM (SELECT UNNEST((SELECT analysis FROM previous_version).Measures) as meas)
29+
),
30+
current_tables AS (
31+
SELECT
32+
tab.TableName,
33+
tab.RowsCount,
34+
tab.TableSize,
35+
part.RefreshedTime
36+
FROM (SELECT UNNEST((SELECT analysis FROM current_version).Tables) as tab),
37+
(SELECT UNNEST((SELECT analysis FROM current_version).Partitions) as part)
38+
WHERE tab.TableName = part.TableName
39+
),
40+
previous_tables AS (
41+
SELECT
42+
tab.TableName,
43+
tab.RowsCount,
44+
tab.TableSize,
45+
part.RefreshedTime
46+
FROM (SELECT UNNEST((SELECT analysis FROM previous_version).Tables) as tab),
47+
(SELECT UNNEST((SELECT analysis FROM previous_version).Partitions) as part)
48+
WHERE tab.TableName = part.TableName
49+
)
50+
SELECT
51+
'Measure Changes' as ChangeType,
52+
c.MeasureName as Name,
53+
c.TableName,
54+
CASE
55+
WHEN p.MeasureName IS NULL THEN 'Added'
56+
WHEN c.MeasureExpression != p.MeasureExpression THEN 'Modified'
57+
ELSE 'Unchanged'
58+
END as Status,
59+
c.MeasureExpression as CurrentDefinition,
60+
p.MeasureExpression as PreviousDefinition
61+
FROM current_measures c
62+
LEFT JOIN previous_measures p ON c.MeasureName = p.MeasureName AND c.TableName = p.TableName
63+
WHERE p.MeasureName IS NULL OR c.MeasureExpression != p.MeasureExpression
64+
65+
UNION ALL
66+
67+
SELECT
68+
'Table Size Changes' as ChangeType,
69+
c.TableName as Name,
70+
NULL as TableName,
71+
'Modified' as Status,
72+
CONCAT(
73+
'Rows: ', c.RowsCount, ' (',
74+
CASE WHEN c.RowsCount > p.RowsCount THEN '+' ELSE '' END,
75+
c.RowsCount - p.RowsCount, ') | ',
76+
'Size: ', ROUND(c.TableSize / 1024.0 / 1024.0, 2), 'MB (',
77+
CASE WHEN c.TableSize > p.TableSize THEN '+' ELSE '' END,
78+
ROUND((c.TableSize - p.TableSize) / 1024.0 / 1024.0, 2), 'MB) | ',
79+
'Last Refresh: ', c.RefreshedTime
80+
) as CurrentDefinition,
81+
CONCAT(
82+
'Rows: ', p.RowsCount, ' | ',
83+
'Size: ', ROUND(p.TableSize / 1024.0 / 1024.0, 2), 'MB | ',
84+
'Last Refresh: ', p.RefreshedTime
85+
) as PreviousDefinition
86+
FROM current_tables c
87+
INNER JOIN previous_tables p ON c.TableName = p.TableName
88+
WHERE c.RowsCount != p.RowsCount OR ABS(c.TableSize - p.TableSize) > 1024
89+
ORDER BY ChangeType, Status DESC, Name;
90+
```
91+
92+
## Batch Analysis Across Multiple Files
93+
94+
**Search for DAX functions across all models:**
95+
```sql
96+
WITH model_measures AS (
97+
SELECT
98+
file,
99+
UNNEST(pbix2vpax(file).Measures) as meas
100+
FROM (SELECT unnest(glob('data/reports/**/*.pbix')) as file)
101+
)
102+
SELECT
103+
file,
104+
meas.TableName,
105+
meas.MeasureName,
106+
meas.MeasureExpression,
107+
CASE
108+
WHEN meas.MeasureExpression ILIKE '%USERELATIONSHIP%' THEN 'USERELATIONSHIP'
109+
WHEN meas.MeasureExpression ILIKE '%CALCULATE%' THEN 'CALCULATE'
110+
WHEN meas.MeasureExpression ILIKE '%TREATAS%' THEN 'TREATAS'
111+
WHEN meas.MeasureExpression ILIKE '%CROSSFILTER%' THEN 'CROSSFILTER'
112+
END as DAXFunction
113+
FROM model_measures
114+
WHERE meas.MeasureExpression ILIKE '%USERELATIONSHIP%'
115+
OR meas.MeasureExpression ILIKE '%TREATAS%'
116+
OR meas.MeasureExpression ILIKE '%CROSSFILTER%'
117+
ORDER BY DAXFunction, file, meas.MeasureName;
118+
```
119+
120+
**Find models with specific table structures:**
121+
```sql
122+
-- Find all models that have a 'Date' table with specific columns
123+
WITH model_columns AS (
124+
SELECT
125+
REGEXP_EXTRACT(file, '([^/]+)\.pbix$', 1) as ModelName,
126+
file,
127+
col.TableName,
128+
col.ColumnName,
129+
col.DataType
130+
FROM (SELECT unnest(glob('data/reports/**/*.pbix')) as file),
131+
LATERAL (SELECT UNNEST(pbix2vpax(file).Columns) as col)
132+
WHERE col.TableName = 'Date'
133+
)
134+
SELECT
135+
ModelName,
136+
file,
137+
STRING_AGG(ColumnName, ', ' ORDER BY ColumnName) as DateColumns,
138+
COUNT(*) as ColumnCount
139+
FROM model_columns
140+
GROUP BY ModelName, file
141+
HAVING COUNT(*) >= 5 -- Models with at least 5 date columns
142+
ORDER BY ColumnCount DESC;
143+
```

README.md

Lines changed: 38 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -170,39 +170,51 @@ ORDER BY part.RecordCount DESC;
170170

171171
#### Advanced Analysis Examples
172172

173-
**Model size breakdown:**
174-
```sql
175-
WITH vpax AS (
176-
SELECT UNNEST(pbix2vpax('Adventure Works DW 2020.pbix').Tables) as t
177-
),
178-
table_sizes AS (
179-
SELECT
180-
t.TableName,
181-
t.TableSize
182-
FROM vpax
183-
)
184-
SELECT
185-
TableName,
186-
TableSize / 1024.0 / 1024.0 as SizeMB,
187-
100.0 * TableSize / SUM(TableSize) OVER () as PercentOfTotal
188-
FROM table_sizes
189-
ORDER BY TableSize DESC;
190-
```
191-
192-
**Measure catalog with expressions:**
173+
**Find all models containing a specific measure:**
193174
```sql
194175
SELECT
176+
file,
195177
meas.TableName,
196178
meas.MeasureName,
197-
meas.DataType,
198179
meas.MeasureExpression,
199-
meas.FormatString,
200-
meas.IsHidden
201-
FROM (SELECT UNNEST(pbix2vpax('Adventure Works DW 2020.pbix').Measures) as meas)
202-
WHERE NOT meas.IsHidden
203-
ORDER BY meas.TableName, meas.MeasureName;
180+
list_count((SELECT pbix2vpax(file).Tables)) as TotalTables,
181+
(SELECT SUM(t.TableSize) FROM (SELECT UNNEST(pbix2vpax(file).Tables) as t)) / 1024.0 / 1024.0 as ModelSizeMB
182+
FROM (
183+
SELECT unnest(glob('data/reports/**/*.pbix')) as file
184+
) files,
185+
LATERAL (
186+
SELECT UNNEST(pbix2vpax(file).Measures) as meas
187+
)
188+
WHERE LOWER(meas.MeasureName) LIKE '%total sales%'
189+
OR LOWER(meas.MeasureExpression) LIKE '%total sales%'
190+
ORDER BY file, meas.TableName, meas.MeasureName;
204191
```
205192

193+
**Audit model freshness and size across a folder:**
194+
```sql
195+
SELECT
196+
REGEXP_EXTRACT(file, '([^/]+)\.pbix$', 1) as FileName,
197+
list_count(vpax.Tables) as TableCount,
198+
list_count(vpax.Measures) as MeasureCount,
199+
list_count(vpax.Relationships) as RelationshipCount,
200+
SUM(tab.RowsCount) as TotalRows,
201+
SUM(tab.TableSize) / 1024.0 / 1024.0 as ModelSizeMB,
202+
MAX(part.RefreshedTime) as LastRefreshTime,
203+
CASE
204+
WHEN MAX(part.RefreshedTime) < CURRENT_DATE - INTERVAL '7 days' THEN '⚠️ Stale'
205+
WHEN MAX(part.RefreshedTime) < CURRENT_DATE - INTERVAL '2 days' THEN '⚡ Recent'
206+
ELSE '✅ Fresh'
207+
END as FreshnessStatus
208+
FROM (
209+
SELECT
210+
unnest(glob('data/reports/**/*.pbix')) as file,
211+
pbix2vpax(unnest(glob('data/reports/**/*.pbix'))) as vpax
212+
),
213+
LATERAL (SELECT UNNEST(vpax.Tables) as tab),
214+
LATERAL (SELECT UNNEST(vpax.Partitions) as part)
215+
GROUP BY file
216+
ORDER BY LastRefreshTime DESC;
217+
```
206218

207219
**Export to JSON for external analysis:**
208220
```sql
@@ -211,45 +223,6 @@ COPY (
211223
) TO 'model_analysis.json';
212224
```
213225

214-
**Create a summary report:**
215-
```sql
216-
WITH vpax AS (
217-
SELECT pbix2vpax('Adventure Works DW 2020.pbix') as analysis
218-
)
219-
SELECT
220-
'Model Summary' as Section,
221-
list_count(vpax.analysis.Tables) as TableCount,
222-
list_count(vpax.analysis.Columns) as ColumnCount,
223-
list_count(vpax.analysis.Measures) as MeasureCount,
224-
list_count(vpax.analysis.Relationships) as RelationshipCount,
225-
list_count(vpax.analysis.UserHierarchies) as HierarchyCount,
226-
(SELECT SUM(tab.TableSize) FROM (SELECT UNNEST(vpax.analysis.Tables) as tab)) / 1024.0 / 1024.0 as TotalModelSizeMB
227-
FROM vpax;
228-
```
229-
230-
**Compare multiple models:**
231-
```sql
232-
WITH
233-
model_a AS (
234-
SELECT
235-
'Model A' as ModelName,
236-
UNNEST(pbix2vpax('model_a.pbix').Tables).TableName as TableName,
237-
UNNEST(pbix2vpax('model_a.pbix').Tables).RowsCount as RowCount,
238-
UNNEST(pbix2vpax('model_a.pbix').Tables).TableSize as TableSize
239-
),
240-
model_b AS (
241-
SELECT
242-
'Model B' as ModelName,
243-
UNNEST(pbix2vpax('model_b.pbix').Tables).TableName as TableName,
244-
UNNEST(pbix2vpax('model_b.pbix').Tables).RowsCount as RowCount,
245-
UNNEST(pbix2vpax('model_b.pbix').Tables).TableSize as TableSize
246-
)
247-
SELECT * FROM model_a
248-
UNION ALL
249-
SELECT * FROM model_b
250-
ORDER BY ModelName, TableSize DESC;
251-
```
252-
253226
## Installing the extension
254227

255228
```sql

0 commit comments

Comments
 (0)