Привет, Хабр! С каждым годом ИИ способен решать более сложные задачи, одной из задач является понимание DAX, связанных предметных областей и генерация кода. Можно выделить несколько задач, которые не являются первостепенными, тем не менее актуальны для анализа или работы в Power BI, например, от простейших — создание клиента для выполнения DAX запросов в Power BI из произвольной среды (например, из .NET приложения) и импорт метаданных TOM модели, до более сложных задач — экспорта схемы данных и самих данных из Power BI в произвольную СУБД (понятно, что такая задача не всегда актуальна с точки зрения ETL, т.к. проще взять данные из исходных источников, а не из Power BI, но польза решения задачи «интуитивно понятна» пользователю) и задач генерации SQL запросов на основе DAX для заданной СУБД, причем результаты сгенерированного SQL должны совпадать с результатами DAX запросов.

Интересующимся применением ИИ на примере DAX из Power BI — добро пожаловать под кат :)

1. Выполнение запроса DAX к Power BI

Бывает актуально выполнить запрос DAX к Power BI из сторонней среды, например, из C# приложения, и для быстрого построения работоспособного прототипа удобно применить ИИ. Необязательно использовать серверную версию Power BI, можно даже взять локальный Power BI, достаточно посмотреть порт Tabular Server в DAX Studio.

Любой ИИ справляется с задачей с первой или второй попытки и применяет AdomdConnection, например, Cursor с настройками по умолчанию. Также вместо сгенерированного ИИ кода при необходимости можно использовать уже готовые имплементации — например, метод ExecuteDaxQueryEnumerable из пакета DaxSharp.

var connectionString =
    "Provider=MSOLAP;" +
    "Data Source=localhost:50181;";

using var conn = new AdomdConnection(connectionString);
conn.Open();

var dax = @"
EVALUATE
	SUMMARIZECOLUMNS(
		product[brandname],
		customer[customername],
		FILTER(product, product[classname] = ""Regular""),
		""Measure"", CALCULATE(
			SUM(sales[salesamount]),
			FILTER(product, product[manufacturer] = ""Contoso, Ltd""),
			REMOVEFILTERS(product),
			SUMMARIZE(
				product,
				product[brandname],
				product[colorname]
			)
		)
	)
";

using var cmd = new AdomdCommand(dax, conn);
using var reader = cmd.ExecuteReader();

while (reader.Read())
{
    for (int i = 0; i < reader.FieldCount; i++)
Console.Write(reader.GetValue(i) + "\t");

    Console.WriteLine();
}

Зачастую получаемый код с помощью ИИ выглядит больше как работоспособный прототип и нуждается в доработке, такие результаты больше подходит для целей исследования, анализа или прототипирования, тем не менее, это расширяет возможности разработчиков и аналитиков.

2. Получение метаданных TOM модели из Power BI

Можно получать метаданные TOM модели из Power BI — описание таблиц и их колонок, связи между таблицами. Использование ИИ значительно упрощает задачу и позволяет получить нужные результаты сразу, без глубокого изучения SQL-подобного языка запросов DMV (Dynamic Management Views). Такие метаданные могут быть полезны для любой другой последующей обработки - например, промптов с учетом TOM модели из Power BI. С этим любой ИИ справляется и ускоряет разработку. Например, с первой или второй попытки Cursor может сгенерировать код на C# для DVM запросов и генерации описания TOM модели в виде (по аналогии с методом GetDatabaseSchemaDescription пакета DaxSharp):

Table customer, columns:
  customer_id (System.Int64, nullable)
  cutomer_name (System.String, nullable)
  customer_gender (System.String, nullable)

Table product, columns:
  product_id (System.Int64, nullable)
  product_name (System.String, nullable)
  product_brand (System.String, nullable)
  product_color (System.String, nullable)

Table sales, columns:
  order_number (System.Int64, nullable)
  customer_id (System.Int64, nullable)
  product_id (System.Int64, nullable)
  quantity (System.Int64, nullable)
  amount (System.Double, nullable)
  orderdate (System.DateTime, nullable)

Также можно добавить описание связей между таблицами и любую другую доступную в TOM информацию.

3. Экспорт данных из Power BI

Можно экспортировать данные из PBI — на основе полученных метаданных ИИ генерирует скрипты создания таблиц в любой СУБД (например, в методе ExportAllTables из пакета DaxSharp имплементировано для PostgreSQL) и упрощает экспорт из PBI. Понятно, что сам по себе экспорт из Power BI может быть антипаттерном с точки зрения ETL процессов, и может больше подходить для целей анализа, и более корректным подходом является импорт данных из исходных источников, из которых данные попадают в Power BI, а не из самого Power BI, однако польза от такого экспорта из Power BI «интуитивно понятна» для пользователя. Также ИИ позволяет быстро реализовать экспорт для различных СУБД, не только для PostgreSQL. Конечно, в схеме данных, полученной в результате экспорта, может не хватать индексов и т.д., она может быть первым приближением, но в общем и целом работает.

Например, для рассмотрим схему данных:

Cursor за одну-две попытки генерирует код на C# на генерации PostgreSQL схемы данных на основе произвольной TOM модели, а также генерирует код на C# для чтения из Power BI данных и заполнения PostgreSQL таблиц, причем логика экспорта генерируется с учетом групп по 1000 записей.

4. Генерация SQL требуемого диалекта по DAX запросу

Используя все 3 предыдущих пункта, можно с помощью ИИ итеративно генерировать SQL по DAX (например, для PostgreSQL, как это имплементировано в методе ConvertDaxToSqlWithValidation из пакета DaxSharp) и сверять результаты с Power BI, при несовпадении — описать ошибку для ИИ и спросить снова. Можно сказать, что это простейший инструмент для быстрого экспорта дашбородов PBI в любую СУБД с любым SQL диалектом.

Например, Cursor с первой-второй попытки генерирует код для итеративного построения SQL для заданной СУБД для заданного DAX запроса, причем используется OpenAI API для генерации SQL и учитываются результаты выполнения DAX запроса в Power BI, при расхождении результатов SQL и DAX запроса к Power BI — расхождения описываются в промпте к OpenAI API и генерируется очередной SQL с исправлением.

Например, для следующего DAX даже модель 4o позволяет получить SQL для PostgreSQL, причем результаты DAX запроса и SQL запроса в PostgreSQL совпадают:

EVALUATE
SUMMARIZECOLUMNS (
    product[product_color],
    customer[customer_gender],
    FILTER ( customer, customer[customer_gender] = "M" ),
    "Total Sales",
        CALCULATE (
            SUM ( sales[amount] ),
            FILTER ( product, product[product_color] IN { "Green", "Silver" } )
        )
)

Генерируемый промпт к модели 4o на основе кода Cursor:

Convert the following DAX query to a PostgreSQL SQL query.

Database Schema:
PostgreSQL Schema Name: public

Table: public."customer"
Columns:
  - "customer_id" (BIGINT, nullable)
  - "cutomer_name" (TEXT, nullable)
  - "customer_gender" (TEXT, nullable)

Table: public."product"
Columns:
  - "product_id" (BIGINT, nullable)
  - "product_name" (TEXT, nullable)
  - "product_brand" (TEXT, nullable)
  - "product_color" (TEXT, nullable)

Table: public."sales"
Columns:
  - "order_number" (BIGINT, nullable)
  - "customer_id" (BIGINT, nullable)
  - "product_id" (BIGINT, nullable)
  - "quantity" (BIGINT, nullable)
  - "amount" (DOUBLE PRECISION, nullable)
  - "orderdate" (TIMESTAMP, nullable)



DAX Query:
EVALUATE
SUMMARIZECOLUMNS(
	product[product_color],
	customer[customer_gender],
	FILTER(
		customer,
		customer[customer_gender] = "M"
	),
	"Total Sales", CALCULATE(
		SUM(sales[amount]),
		FILTER(
			product,
			product[product_color] IN {
				"Green",
				"Silver"
			}
		)
	)
)

PostgreSQL Schema Name: public

Generate a valid PostgreSQL SQL query that produces the same results as the DAX query.
Use the provided database schema information to correctly join tables and reference columns.
Return only the SQL query without any explanations or markdown formatting.

Сгенерированный при помощи модели 4o PostgreSQL запрос:

SELECT
    p.product_color,
    c.customer_gender,
    SUM(s.amount) AS "Total Sales"
FROM public.sales AS s
JOIN public.customer AS c
    ON s.customer_id = c.customer_id
JOIN public.product AS p
    ON s.product_id = p.product_id
WHERE c.customer_gender = 'M'
  AND p.product_color IN ('Green', 'Silver')
GROUP BY
    p.product_color,
    c.customer_gender;

Вывод

Использование ИИ в связке с DAX и Power BI уже сегодня позволяет существенно упростить и ускорить решение как прикладных, так и исследовательских BI-задач — от работы с метаданными и прототипирования до автоматизации экспорта и трансляции запросов между языками. Хотя такие решения не всегда заменяют «классические» подходы и требуют валидации, они открывают новые возможности для аналитиков и разработчиков, снижая порог входа и повышая скорость экспериментов.

Надеюсь, приведенные примеры использования ИИ для BI задач в рамках DAX и Power BI могут быть полезны, удачных промптов и дашбордов :)

Комментарии (0)