<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sergei Semenkov</title>
    <description>The latest articles on DEV Community by Sergei Semenkov (@sergeisemenkov).</description>
    <link>https://dev.to/sergeisemenkov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F563580%2F53802125-95ee-4bc2-81c7-c45a8eb7fedb.jpg</url>
      <title>DEV Community: Sergei Semenkov</title>
      <link>https://dev.to/sergeisemenkov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sergeisemenkov"/>
    <language>en</language>
    <item>
      <title>Power BI on Databricks Metric Views: a live connection, with the measures kept in Databricks</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Thu, 05 Nov 2026 10:52:07 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/power-bi-on-databricks-metric-views-a-live-connection-with-the-measures-kept-in-databricks-5cel</link>
      <guid>https://dev.to/sergeisemenkov/power-bi-on-databricks-metric-views-a-live-connection-with-the-measures-kept-in-databricks-5cel</guid>
      <description>&lt;p&gt;&lt;em&gt;As of November 2026: eMondrian Community 2026.11.05.1 (server 10.0.74, modules 0.0.0.89). You need Power BI Desktop, a Databricks SQL warehouse with a metric view and, for the Power BI Service, a Windows machine for the on-premises data gateway.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Databricks Metric Views let you define a metric once, in Unity Catalog, and query it from SQL, notebooks, dashboards and Genie. Power BI is the tool most teams still report in, and right now it can't use those definitions properly. I connected the two through a semantic layer, live, and checked the totals that usually go wrong.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I'm the author of eMondrian, the open-source semantic layer used here.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short:&lt;/strong&gt; eMondrian connects Power BI to Databricks metric views live. Power BI Desktop and the Power BI Service connect to eMondrian as to Analysis Services and send DAX. eMondrian turns each query into flat &lt;code&gt;MEASURE()&lt;/code&gt; SQL that the Databricks SQL warehouse runs against the metric view. The measures stay defined once, in the metric view: no Import, no hand-written Native query and no copy of the formulas in DAX. Distinct counts and ratios show correct totals at every level, because Databricks computes each total from the view's own definition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why keep the metrics in Databricks
&lt;/h2&gt;

&lt;p&gt;A metric view is a YAML definition next to the data: the source table, joins, dimensions and measures such as &lt;code&gt;COUNT(DISTINCT customer_id)&lt;/code&gt; or &lt;code&gt;SUM(revenue) / SUM(orders)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Keeping metrics there has practical advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One definition for every consumer.&lt;/strong&gt; SQL users, notebooks, ML pipelines, AI/BI dashboards and Genie all read the same measure. Nobody re-types it in DAX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Changes in one place.&lt;/strong&gt; Rename a column or change a formula, and every consumer gets it. There are no copies in individual .pbix files to fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The grain is handled by the engine.&lt;/strong&gt; &lt;code&gt;MEASURE(unique_customers)&lt;/code&gt; grouped by month is computed per month, and grouped by year it's computed per year. A distinct count or a ratio is never added up from smaller pieces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unity Catalog is where the data team works already:&lt;/strong&gt; lineage, permissions and reviews of the definitions are in the same place as the tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What goes wrong with Power BI today
&lt;/h2&gt;

&lt;p&gt;Querying a metric view needs special SQL: each measure wrapped in &lt;code&gt;MEASURE()&lt;/code&gt;, an explicit &lt;code&gt;GROUP BY&lt;/code&gt;, no &lt;code&gt;SELECT *&lt;/code&gt;, no joins in the query. Power BI doesn't generate that.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BI compatibility mode is gone.&lt;/strong&gt; It used to be an option in the Databricks connector: Databricks rewrote plain &lt;code&gt;SUM&lt;/code&gt; into the measure definitions, and even then &lt;code&gt;COUNT DISTINCT&lt;/code&gt; and &lt;code&gt;MEDIAN&lt;/code&gt; failed or gave wrong results. Databricks now notes that the option "is no longer available in the Power BI connector".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What's left is Native query or a wrapper view.&lt;/strong&gt; With Native query you hand-write &lt;code&gt;MEASURE()&lt;/code&gt; SQL for each table in DirectQuery. That doesn't scale beyond a few visuals. A standard view that wraps the metric view fixes the grain in advance, so Power BI adds its rows up like an import.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import mode re-aggregates.&lt;/strong&gt; Load a metric view at month grain and let Power BI sum it, and the yearly total of a distinct count is wrong. People then rebuild the ratio in DAX, which is the duplication metric views were meant to remove.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Converting is copying.&lt;/strong&gt; Tools such as Tabular Editor's Semantic Bridge translate a metric view into a Tabular model. That works for many measures, but the definitions now live in two places again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Fabric idea "Enable native Power BI integration with Databricks Metric View" has more than 800 votes, and its comments are mostly about these points.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works: a live model in between
&lt;/h2&gt;

&lt;p&gt;eMondrian holds a model whose cube points at the metric view. To Power BI it looks like Analysis Services: Power BI connects &lt;strong&gt;live&lt;/strong&gt; and sends DAX. eMondrian turns each query into flat SQL for the SQL warehouse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;`order_year`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MEASURE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;`mv`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`unique_customers`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;`catalog`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`schema`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`orders_mv`&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;`mv`&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;`order_status`&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Open'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Processing'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="nv"&gt;`order_year`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No nesting, no joins, no subqueries, no GROUPING SETS: the rules of metric views are kept. The measure is computed by Databricks, from its own definition. eMondrian doesn't hold a copy of the formula.&lt;/p&gt;

&lt;p&gt;Excel PivotTables connect to the same model over the same address (MDX), and AI agents over MCP.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzq12j0ylw19gj4seotge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzq12j0ylw19gj4seotge.png" alt="How a query travels from the browser to the metric view and back: Power BI Service, the data gateway with its built-in Analysis Services connection, eMondrian, the Databricks SQL warehouse" width="799" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure types that fit metric views
&lt;/h2&gt;

&lt;p&gt;In an eMondrian schema each measure says how it may be rolled up. Two settings matter for metric views.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additive measures&lt;/strong&gt; (sums, counts of rows). Declared with &lt;code&gt;aggregator="sum"&lt;/code&gt;. eMondrian may cache a result and add months into a year itself, which saves trips to the warehouse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-additive measures&lt;/strong&gt; (distinct counts, ratios, averages, medians). Declared as non-additive (&lt;code&gt;aggregator="distinct-count"&lt;/code&gt;) and computed by the database (&lt;code&gt;aggregatorImplementation="MEASURE"&lt;/code&gt;). eMondrian never adds them up. Every level a visual shows, every subtotal and the grand total is asked from Databricks with its own &lt;code&gt;GROUP BY&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Measure&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Unique Customers"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"unique_customers"&lt;/span&gt;
         &lt;span class="na"&gt;aggregator=&lt;/span&gt;&lt;span class="s"&gt;"distinct-count"&lt;/span&gt; &lt;span class="na"&gt;aggregatorImplementation=&lt;/span&gt;&lt;span class="s"&gt;"MEASURE"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Measure&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Order Count"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"order_count"&lt;/span&gt;
         &lt;span class="na"&gt;aggregator=&lt;/span&gt;&lt;span class="s"&gt;"sum"&lt;/span&gt; &lt;span class="na"&gt;aggregatorImplementation=&lt;/span&gt;&lt;span class="s"&gt;"MEASURE"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which one to use depends only on the measure's expression in the metric view:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Expression in the metric view&lt;/th&gt;
&lt;th&gt;aggregator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;a single &lt;code&gt;SUM(x)&lt;/code&gt;, &lt;code&gt;COUNT(x)&lt;/code&gt; or &lt;code&gt;COUNT_IF(cond)&lt;/code&gt;, with or without &lt;code&gt;FILTER (WHERE …)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sum&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;a single &lt;code&gt;MIN(x)&lt;/code&gt; / &lt;code&gt;MAX(x)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;min&lt;/code&gt; / &lt;code&gt;max&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;COUNT(DISTINCT x)&lt;/code&gt;, a ratio such as &lt;code&gt;SUM(a) / SUM(b)&lt;/code&gt;, &lt;code&gt;SUM(a) * 2&lt;/code&gt;, &lt;code&gt;AVG&lt;/code&gt;, &lt;code&gt;MEDIAN&lt;/code&gt;, &lt;code&gt;PERCENTILE&lt;/code&gt;, &lt;code&gt;APPROX_*&lt;/code&gt;, window measures, references to other measures&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;distinct-count&lt;/code&gt; (never rolled up)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When in doubt, choose non-additive. A wrong &lt;code&gt;sum&lt;/code&gt; gives wrong totals without any error. A wrong non-additive setting only costs an extra query.&lt;/p&gt;

&lt;p&gt;The schema also needs the size of each level (how many members it has). Without it the engine would send &lt;code&gt;COUNT(DISTINCT …)&lt;/code&gt; to the view to find out. With sizes in place every statement stays a plain &lt;code&gt;SELECT … MEASURE() … GROUP BY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Filters work the same way: with two order statuses selected, the total is the metric view's own figure for those two statuses, not the sum of two rows. An Excel PivotTable gets the same totals, including when you filter the pivot and Excel sends a subselect.&lt;/p&gt;

&lt;p&gt;The trade-off: a visual with several non-additive measures may need several SQL statements, and each one runs on the warehouse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time intelligence lives in the model
&lt;/h2&gt;

&lt;p&gt;On a live connection to a multidimensional model, Power BI doesn't let you write report measures, so &lt;code&gt;TOTALYTD&lt;/code&gt; or &lt;code&gt;SAMEPERIODLASTYEAR&lt;/code&gt; aren't an option. Year-to-date, same period last year, previous year, year-over-year and a rolling three months are calculated measures in the eMondrian schema instead. The MCP tool &lt;code&gt;add_time_measures&lt;/code&gt; writes them for the measures you name; the cube authoring guide explains the templates.&lt;/p&gt;

&lt;p&gt;They work for non-additive measures too. Year-to-date unique customers for December is one query over months 1–12, and the result is the metric view's own figure for the year, not the sum of twelve months:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;MEASURE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;`mv`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`unique_customers`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;`catalog`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`schema`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`orders_mv`&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;`mv`&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;`order_year`&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1996&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nv"&gt;`order_month`&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a test setup that applies the metric view query rules, these measures matched hand-written &lt;code&gt;MEASURE()&lt;/code&gt; SQL in both the Excel and the Power BI query shapes, including a year picked in a Power BI slicer and a rolling three months across the new year. Every query was a single flat &lt;code&gt;MEASURE()&lt;/code&gt; statement. In Power BI Desktop, checked on eMondrian's FoodMart sample, a year chosen in a slicer keeps all twelve months, and the total row shows the year's figures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let an agent write the model
&lt;/h2&gt;

&lt;p&gt;You don't write this schema by hand. eMondrian's MCP server includes a cube authoring guide with a section on metric views: the rules above, the time hierarchy, the metric view SQL rules, and a complete example.&lt;/p&gt;

&lt;p&gt;The agent needs two things from Databricks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the view's definition, &lt;code&gt;DESCRIBE TABLE EXTENDED catalog.schema.orders_mv AS JSON&lt;/code&gt;, which marks each field as a measure or a dimension and includes the YAML;&lt;/li&gt;
&lt;li&gt;the number of distinct values of each dimension field, a &lt;code&gt;GROUP BY&lt;/code&gt; without measures.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From those it writes the schema, checks it and saves it.&lt;/p&gt;

&lt;p&gt;This is deliberate: there is no fixed converter from metric view to cube. A converter would make the same choices for every view, while a real model needs decisions that depend on the data and on how people report: which fields form a hierarchy, what to name things, which measures to hide, which roles to add. The agent makes those choices with you, following the guide, and you review the result like any other change.&lt;/p&gt;

&lt;p&gt;In my test a new agent session had only the guide, the JSON and the counts. It produced a schema whose figures matched the hand-written one cell for cell: all measures by year and by month, the IN filter case, and status by priority. It chose &lt;code&gt;sum&lt;/code&gt; for the two counts and the non-additive setting for the distinct count and the ratio.&lt;/p&gt;

&lt;p&gt;The agent runs these two queries with its own Databricks access, for example the Databricks MCP server, and under its own permissions. You can also run them in the SQL editor and paste the results. eMondrian's MCP tools only work with the model (MDX and DAX); reading the source is left to Databricks' own tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;You need Claude Code, Docker, Power BI Desktop on Windows, and a Databricks workspace with a metric view, a SQL warehouse and a personal access token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Start eMondrian Community.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/eMondrian/emondrian-community
&lt;span class="nb"&gt;cd &lt;/span&gt;emondrian-community
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
./setup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To change the port, edit &lt;code&gt;EMONDRIAN_PORT&lt;/code&gt; in the copied &lt;code&gt;.env&lt;/code&gt;; &lt;code&gt;setup.sh&lt;/code&gt; lists any settings your &lt;code&gt;.env&lt;/code&gt; leaves out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Add a licence key.&lt;/strong&gt; The Power BI (DAX) and MCP modules need one. Request the free 30-day key at &lt;a href="https://emondrian.com/license?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=databricks-metric-views" rel="noopener noreferrer"&gt;emondrian.com/license&lt;/a&gt; and put the &lt;code&gt;.lic&lt;/code&gt; file into &lt;code&gt;modules/&lt;/code&gt;. No restart is needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Connect eMondrian to Databricks.&lt;/strong&gt; The Databricks JDBC driver isn't in the image: download it from Databricks and mount it into the server's &lt;code&gt;lib&lt;/code&gt; folder. The connection settings go into an env file, so the token never appears in a schema or in &lt;code&gt;datasources.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.override.yml&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;eMondrian&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;databricks.env&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./drivers/databricks-jdbc.jar:/usr/local/tomcat/lib/databricks-jdbc.jar:ro&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the name of the jar you downloaded in place of &lt;code&gt;databricks-jdbc.jar&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# databricks.env (keep it out of Git)
&lt;/span&gt;&lt;span class="py"&gt;EMONDRIAN_DATABRICKS_HOST&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;workspace host&amp;gt;&lt;/span&gt;
&lt;span class="py"&gt;EMONDRIAN_DATABRICKS_HTTP_PATH&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;SQL warehouse HTTP path&amp;gt;&lt;/span&gt;
&lt;span class="py"&gt;EMONDRIAN_DATABRICKS_CATALOG&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;catalog&amp;gt;&lt;/span&gt;
&lt;span class="py"&gt;EMONDRIAN_DATABRICKS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;token&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;docker compose up -d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Give Claude Code both servers.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http emondrian http://localhost/emondrian/mcp
claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http databricks https://&amp;lt;workspace host&amp;gt;/api/2.0/mcp/sql &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$DATABRICKS_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Databricks SQL server has a tool that runs any statement (&lt;code&gt;execute_sql&lt;/code&gt;) and a read-only one (&lt;code&gt;execute_sql_read_only&lt;/code&gt;). Allow only the read-only tool and &lt;code&gt;poll_sql_result&lt;/code&gt;; the agent needs nothing else. &lt;code&gt;DESCRIBE&lt;/code&gt;, &lt;code&gt;SHOW CREATE TABLE&lt;/code&gt; and &lt;code&gt;SELECT … MEASURE() … GROUP BY&lt;/code&gt; all pass through it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Ask for the cube.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Two MCP servers are connected: "databricks" and "emondrian". In Databricks there is a metric view &lt;code&gt;&amp;lt;catalog&amp;gt;.&amp;lt;schema&amp;gt;.orders_mv&lt;/code&gt;. Build an eMondrian cube over it: follow the eMondrian cube authoring guide (it has a section on metric views), read what you need about the view through the databricks tools, write the schema, validate it, and register it in eMondrian as a new catalog named "Orders". The server already has the Databricks connection as environment variables; never write the host, path or token into anything.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The guide is long; Claude Code saves it to a file and reads the metric view section from there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Ask it to check its own work.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Compare at least three figures from the "Orders" cube with MEASURE() SQL on the metric view, including the distinct-count measure for one whole year against the sum of that year's months: they must differ, and the cube must match the year. Then add time measures with add_time_measures (preview first, then save) for one additive and one distinct-count measure, and check one year-to-date value against SQL. Show the comparisons as a table.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;7. Ask for the Power BI project.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Create a Power BI Desktop project for the "Orders" cube with the eMondrian report tools: one page with a table of months showing the main measures and their year-to-date measures, and a slicer on the year. Connect it to &lt;code&gt;http://&amp;lt;eMondrian machine&amp;gt;/xmla&lt;/code&gt;. Write the files into ./orders-report and pack the folder into orders-report.zip.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use the address by which Power BI Desktop's machine reaches eMondrian: the server's name or IP, or &lt;code&gt;localhost&lt;/code&gt; if Desktop runs on the same machine. If you leave it out, the agent asks for it. Unzip the archive and open &lt;code&gt;orders-report.pbip&lt;/code&gt; in Power BI Desktop. It connects live, with no data import.&lt;/p&gt;

&lt;p&gt;In my run each of the three prompts took one to three minutes. The cube figures, the year-to-date measures and every value in the Desktop table matched &lt;code&gt;MEASURE()&lt;/code&gt; SQL on the view, and the year total of the distinct count was the view's own figure for the year, not the sum of its months.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment: two VMs, one for the gateway and one for eMondrian
&lt;/h2&gt;

&lt;p&gt;For the Power BI Service you need the on-premises data gateway in standard mode. It uses its &lt;strong&gt;built-in Analysis Services&lt;/strong&gt; connection to eMondrian, so nothing Databricks-specific is installed on it: no ODBC driver, no custom connector.&lt;/p&gt;

&lt;p&gt;I recommend two separate machines:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Gateway VM&lt;/th&gt;
&lt;th&gt;eMondrian VM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OS&lt;/td&gt;
&lt;td&gt;Windows (the gateway runs only on Windows)&lt;/td&gt;
&lt;td&gt;Linux with Docker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Talks to&lt;/td&gt;
&lt;td&gt;Power BI Service (outbound) and eMondrian&lt;/td&gt;
&lt;td&gt;the gateway and the SQL warehouse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Updates&lt;/td&gt;
&lt;td&gt;monthly gateway releases, Windows restarts&lt;/td&gt;
&lt;td&gt;eMondrian releases&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Why not one machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Different platforms.&lt;/strong&gt; The gateway is a Windows service; eMondrian runs as Linux containers. On one box you end up with Docker on Windows, which is the less common setup to run in production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restarts don't take each other down.&lt;/strong&gt; Gateway updates and Windows patches restart the gateway VM. Excel users and AI agents connected straight to eMondrian keep working.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resources.&lt;/strong&gt; Both do real work per report view: the gateway relays every query, and eMondrian builds SQL and holds the cache. Separate VMs mean neither starves the other, and each can be sized and scaled on its own (a gateway cluster, a larger eMondrian VM).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credentials stay apart.&lt;/strong&gt; The warehouse token lives only on the eMondrian VM. The gateway only knows the XMLA address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Placement.&lt;/strong&gt; Put both in the same virtual network and region as the SQL warehouse. The XMLA endpoint then doesn't need to be reachable from the internet: only the gateway, Excel users on the network and agents use it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setting up the Service is the same as for any eMondrian source: a gateway connection of type Analysis Services, server &lt;code&gt;https://&amp;lt;emondrian-address&amp;gt;/xmla&lt;/code&gt;, database = the catalog name, Windows authentication; then Publish from Desktop. In the test the report and pinned dashboard tiles refreshed through the gateway, and every figure equalled the metric view's own query.&lt;/p&gt;

&lt;p&gt;Plan the warehouse for live use: every click in the report runs on the SQL warehouse, so choose its size and set auto-stop with that in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can Power BI connect live to a Databricks metric view?&lt;/strong&gt;&lt;br&gt;
Yes, through eMondrian. Power BI connects live to eMondrian as to Analysis Services, and eMondrian queries the metric view with &lt;code&gt;MEASURE()&lt;/code&gt; SQL. Power BI's own Databricks connector no longer offers this: BI compatibility mode is gone, and what remains is hand-written Native query SQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it work in the Power BI Service, not only in Desktop?&lt;/strong&gt;&lt;br&gt;
Yes. The on-premises data gateway uses its built-in Analysis Services connection to eMondrian, with no Databricks driver on the gateway. Reports and pinned dashboard tiles refresh through it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are totals of distinct counts and ratios correct?&lt;/strong&gt;&lt;br&gt;
Yes. eMondrian never adds up non-additive measures. Every subtotal and the grand total is a separate &lt;code&gt;MEASURE()&lt;/code&gt; query, so Databricks computes it from the view's definition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I have to rewrite the metric view's measures in DAX?&lt;/strong&gt;&lt;br&gt;
No. The measure formulas stay only in Databricks. The eMondrian schema names the measures and says whether they may be rolled up, and an AI agent can write that schema from the metric view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Excel work too?&lt;/strong&gt;&lt;br&gt;
Yes. Excel PivotTables connect to the same eMondrian model over XMLA and get the same figures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does it cost?&lt;/strong&gt;&lt;br&gt;
eMondrian Community is open source. The Power BI (DAX) and MCP modules need a licence key; a free 30-day key is available. Every report query runs on your SQL warehouse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would this help you?
&lt;/h2&gt;

&lt;p&gt;I'm looking for teams that report in Power BI on Databricks and have hit the problems above. If you've rebuilt metric-view measures in DAX, or your totals stopped matching, I'd like to hear how you handle it now. Leave a comment.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;eMondrian:&lt;/strong&gt; &lt;a href="https://emondrian.com/demo?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=databricks-metric-views" rel="noopener noreferrer"&gt;Demo&lt;/a&gt; · &lt;a href="https://github.com/eMondrian/emondrian-community" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://docs.emondrian.com" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.databricks.com/aws/en/uc-semantics/metric-views/query" rel="noopener noreferrer"&gt;Databricks: query metric views&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.databricks.com/aws/en/uc-semantics/metric-views/bi-tools" rel="noopener noreferrer"&gt;Databricks: metric views with external BI tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.databricks.com/aws/en/partners/bi/bi-metric-view" rel="noopener noreferrer"&gt;Databricks: BI compatibility mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.fabric.microsoft.com/idea/fbc_ideas/enable-native-power-bi-integration-with-databricks-metric-view/4823684" rel="noopener noreferrer"&gt;Fabric Ideas: Enable native Power BI integration with Databricks Metric View&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.tabulareditor.com/features/semantic-bridge.html" rel="noopener noreferrer"&gt;Tabular Editor: Semantic Bridge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/data-integration/gateway/service-gateway-onprem" rel="noopener noreferrer"&gt;Microsoft: on-premises data gateway&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>powerbi</category>
      <category>databricks</category>
      <category>semanticlayer</category>
      <category>dataengineering</category>
    </item>
    <item>
      <title>Power BI Service on ClickHouse, without an ODBC driver on your gateway</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Tue, 03 Nov 2026 13:09:25 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/power-bi-service-on-clickhouse-without-an-odbc-driver-on-your-gateway-1mnn</link>
      <guid>https://dev.to/sergeisemenkov/power-bi-service-on-clickhouse-without-an-odbc-driver-on-your-gateway-1mnn</guid>
      <description>&lt;p&gt;&lt;em&gt;As of November 2026. You need Power BI Desktop, a Power BI account and a Windows machine for the on-premises data gateway.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last week &lt;a href="https://dev.to/sergeisemenkov/claude-builds-a-power-bi-report-on-a-live-model-in-clickhouse-c0k"&gt;Claude built a Power BI report on 182 million flights in ClickHouse&lt;/a&gt;. It ran in Power BI Desktop. The next question is the one every BI team asks: &lt;em&gt;can the rest of the team open it in the Power BI Service?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's how: publish the same live report through the standard gateway, with nothing ClickHouse-specific installed on it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I'm the author of eMondrian, the open-source semantic layer used here.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works: a semantic model in between
&lt;/h2&gt;

&lt;p&gt;eMondrian sits between Power BI and ClickHouse. It holds the model, with cubes, dimensions and measures such as &lt;em&gt;On-Time Rate&lt;/em&gt; defined once. To Power BI it looks like Analysis Services. Power BI connects to it &lt;strong&gt;live&lt;/strong&gt; and sends DAX. eMondrian turns that into SQL for ClickHouse.&lt;/p&gt;

&lt;p&gt;For the Service, that means the gateway uses a connection type it already has built in: &lt;strong&gt;Analysis Services&lt;/strong&gt;. There is no ClickHouse driver or custom connector on the gateway. The gateway only needs to reach eMondrian's HTTPS address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozxcx5yhm3y9v6ndar59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozxcx5yhm3y9v6ndar59.png" alt="How a query travels from the browser to ClickHouse and back: Power BI Service, the data gateway with its built-in Analysis Services connection, eMondrian, ClickHouse" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Official ClickHouse connector&lt;/th&gt;
&lt;th&gt;Through eMondrian&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;On the gateway machine&lt;/td&gt;
&lt;td&gt;ClickHouse ODBC driver&lt;/td&gt;
&lt;td&gt;Nothing extra: built-in Analysis Services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How Power BI queries&lt;/td&gt;
&lt;td&gt;DirectQuery: Power BI writes SQL against the tables&lt;/td&gt;
&lt;td&gt;Live connection to a semantic model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where measures live&lt;/td&gt;
&lt;td&gt;In each .pbix&lt;/td&gt;
&lt;td&gt;Once, in the model; the same in Power BI, Excel and AI agents&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A report with a live connection to eMondrian. Use the one from the &lt;a href="https://dev.to/sergeisemenkov/claude-builds-a-power-bi-report-on-a-live-model-in-clickhouse-c0k"&gt;previous tutorial&lt;/a&gt;. Or connect Power BI Desktop yourself: &lt;strong&gt;Get data → Analysis Services&lt;/strong&gt;, server &lt;code&gt;https://demo.emondrian.com/xmla&lt;/code&gt;, database &lt;code&gt;OnTime&lt;/code&gt;, &lt;strong&gt;Connect live&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;on-premises data gateway&lt;/strong&gt; in &lt;strong&gt;standard mode&lt;/strong&gt; (not personal mode), on a Windows machine that can reach the eMondrian address.&lt;/li&gt;
&lt;li&gt;A Power BI account. On a Free licence you can view your own report in &lt;em&gt;My workspace&lt;/em&gt;. To share it with your team, you need Pro or Premium Per User.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I used the public eMondrian demo, so there was no server to install. Its data is read-only: 182 million US flights in ClickHouse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Add the connection to the gateway
&lt;/h2&gt;

&lt;p&gt;Install the gateway and sign in, if you haven't already. Then, in the Power BI Service: &lt;strong&gt;Settings → Manage connections and gateways → New → On-premises&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gateway:&lt;/strong&gt; your gateway&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection type:&lt;/strong&gt; Analysis Services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server:&lt;/strong&gt; &lt;code&gt;https://demo.emondrian.com/xmla&lt;/code&gt; (or your eMondrian address)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; &lt;code&gt;OnTime&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; Windows, with an account the gateway can use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy level:&lt;/strong&gt; Organizational&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4mn9afbhqubu1rit7l3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4mn9afbhqubu1rit7l3m.png" alt="The gateway connection: type Analysis Services, server https://demo.emondrian.com/xmla, database OnTime" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save. The gateway needs a Windows account to make the connection; the demo doesn't check it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Publish from Power BI Desktop
&lt;/h2&gt;

&lt;p&gt;Open the report in Desktop and click &lt;strong&gt;Publish&lt;/strong&gt;, then choose a workspace. The Service matches the report to the gateway connection by server and database. If it doesn't, check &lt;strong&gt;Semantic model settings → Gateway and cloud connections&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Open it in the browser
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flqbur71s09bh8dl3040l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flqbur71s09bh8dl3040l.png" alt="The report in the Power BI Service: 2025, all carriers" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every visual queries the model live through the gateway. Nothing is imported into Power BI, and there's no scheduled data refresh to set up for the report itself.&lt;/p&gt;

&lt;p&gt;I clicked through it and compared each number with a direct MDX query on the server. They matched:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2025: &lt;strong&gt;7,001,619 flights, 76.34% on time&lt;/strong&gt;, the same as in Desktop and in the Claude dashboard on the same model;&lt;/li&gt;
&lt;li&gt;carrier DL (Delta) selected: &lt;strong&gt;1,026,332 flights, 79.12%&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;the tooltip for Delta in September: 87.36%;&lt;/li&gt;
&lt;li&gt;clicking American (AA) on the carriers bar cross-filters the page: 973,653 flights, 72.70%;&lt;/li&gt;
&lt;li&gt;cancellation rate by day of week for Delta matches the previous article: Friday 1.73% is the worst day, Wednesday 0.49% the best.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdxav290tysvai6hc902.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdxav290tysvai6hc902.png" alt="The same report with Delta selected" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Speed:&lt;/strong&gt; the eight-visual page opened in &lt;strong&gt;3.6–4.6 seconds&lt;/strong&gt; in the Service through the gateway. In Desktop, connected directly, its slowest visual took 1.7–3.6 seconds. Those were warm runs on a shared public demo, so treat them as a rough idea, not a benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Pin it to a dashboard
&lt;/h2&gt;

&lt;p&gt;Pin a few visuals to a dashboard as usual. The tiles show live data and refresh automatically through the same gateway connection. This requires eMondrian 10.0.62 or later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr4xzqbk0ytxj3ozogi1t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr4xzqbk0ytxj3ozogi1t.png" alt="A dashboard with three pinned tiles" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What about Excel?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Analyze in Excel&lt;/em&gt; from the Service needs a Pro or PPU licence. I didn't test it.&lt;/p&gt;

&lt;p&gt;You don't need the Service for Excel, though. Excel connects to eMondrian directly: &lt;strong&gt;Data → Get Data → From Database → From Analysis Services&lt;/strong&gt;, with the same address. A PivotTable there uses the same model and the same measures as the report.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing this on your own data
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Run eMondrian Community next to your database: &lt;code&gt;git clone https://github.com/eMondrian/emondrian-community&lt;/code&gt; and &lt;code&gt;./setup.sh&lt;/code&gt;. It works with ClickHouse, PostgreSQL, MySQL or any JDBC source.&lt;/li&gt;
&lt;li&gt;Describe your cubes and measures, or ask Claude to draft the schema over MCP.&lt;/li&gt;
&lt;li&gt;Point the gateway's Analysis Services connection at your eMondrian address and publish.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Power BI (DAX) module needs a key; a free 30-day evaluation key is at &lt;a href="https://emondrian.com/license?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=powerbi-service" rel="noopener noreferrer"&gt;emondrian.com/license&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;eMondrian:&lt;/strong&gt; &lt;a href="https://emondrian.com/demo?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=powerbi-service" rel="noopener noreferrer"&gt;Demo&lt;/a&gt; · &lt;a href="https://github.com/eMondrian/emondrian-community" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://docs.emondrian.com" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://clickhouse.com/docs/integrations/powerbi" rel="noopener noreferrer"&gt;ClickHouse: Power BI integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/power-query/connectors/clickhouse" rel="noopener noreferrer"&gt;Microsoft: ClickHouse connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/data-integration/gateway/service-gateway-onprem" rel="noopener noreferrer"&gt;Microsoft: on-premises data gateway&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you put ClickHouse behind the Power BI Service? What broke? Leave a comment.&lt;/p&gt;

</description>
      <category>powerbi</category>
      <category>clickhouse</category>
      <category>semanticlayer</category>
      <category>dataengineering</category>
    </item>
    <item>
      <title>Claude builds a Power BI report on a live model in ClickHouse</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Tue, 27 Oct 2026 13:58:19 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/claude-builds-a-power-bi-report-on-a-live-model-in-clickhouse-c0k</link>
      <guid>https://dev.to/sergeisemenkov/claude-builds-a-power-bi-report-on-a-live-model-in-clickhouse-c0k</guid>
      <description>&lt;p&gt;&lt;em&gt;As of October 2026. You need Windows with Power BI Desktop and Claude Code. Nothing else to install.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last week I showed &lt;a href="https://dev.to/sergeisemenkov/claude-dashboards-on-clickhouse-through-a-semantic-layer-a-10-minute-tutorial-2ami"&gt;Claude building a live dashboard on 182 million flights&lt;/a&gt;. The most common question afterwards: &lt;em&gt;can it do that in Power BI?&lt;/em&gt; That's where most BI teams actually live.&lt;/p&gt;

&lt;p&gt;It can. In this tutorial an AI agent builds a real Power BI project, a page with slicers, KPI cards and charts, with a &lt;strong&gt;live connection&lt;/strong&gt; to a semantic model on ClickHouse. Then you look at it in Power BI Desktop, ask for a change, and look again. Nothing is imported into Power BI, and there's no copy of the data.&lt;/p&gt;

&lt;p&gt;It runs against the public eMondrian demo, so you don't install a server. The agent took about three and a half minutes for the first version and two and a half for the change.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I'm the author of eMondrian, the open-source semantic layer used here.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll build
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd4qeh9z796uj1u55osqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd4qeh9z796uj1u55osqa.png" alt="The finished report in Power BI Desktop, 2025 selected" width="799" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Year and carrier slicers&lt;/li&gt;
&lt;li&gt;KPI cards: flights and on-time rate for the selection&lt;/li&gt;
&lt;li&gt;On-time rate by year, and by month for the selected year&lt;/li&gt;
&lt;li&gt;The largest carriers by flights&lt;/li&gt;
&lt;li&gt;After the change: cancellation rate by day of week&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent wrote every page and visual. I typed two prompts and didn't touch the files.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works, in one paragraph
&lt;/h2&gt;

&lt;p&gt;Power BI Desktop can save a report as a &lt;strong&gt;project (PBIP)&lt;/strong&gt;: a folder of JSON files, one per page and per visual. An agent can write those files. The model lives in eMondrian, an open semantic layer on ClickHouse, where measures like &lt;em&gt;On-Time Rate&lt;/em&gt; are defined once. Power BI connects to it live through its Analysis Services connector and sends DAX, the same way it talks to Analysis Services. The agent never sees raw tables or rows: it reads the model, generates the report files, and validates them before it hands them over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Connect Claude Code to the demo (1 minute)
&lt;/h2&gt;

&lt;p&gt;In an empty folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--scope&lt;/span&gt; project &lt;span class="nt"&gt;--transport&lt;/span&gt; http emondrian https://demo.emondrian.com/emondrian/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This writes a &lt;code&gt;.mcp.json&lt;/code&gt; into the folder; Claude Code asks you once to allow the server when it starts. The demo is public and its data is read-only: 182 million US flights in ClickHouse, behind a model called OnTime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Ask for the first version (3½ minutes)
&lt;/h2&gt;

&lt;p&gt;Start &lt;code&gt;claude&lt;/code&gt; in that folder and paste:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using the eMondrian MCP server, build a Power BI report on the OnTime catalog: a page "On-time performance" with year and carrier slicers, KPI cards for flights and on-time rate, on-time rate by year (line), by month for the selected year, and the largest carriers (bar). Live connection to the model, no import. Validate the report before you finish. Power BI should connect live to &lt;a href="https://demo.emondrian.com/xmla" rel="noopener noreferrer"&gt;https://demo.emondrian.com/xmla&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I ran it in a brand-new Claude Code session; the folder held nothing but the MCP configuration. The agent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;read the model&lt;/strong&gt;: catalogs, the cube, and the field names Power BI will use. That's how it found &lt;em&gt;On-Time Rate&lt;/em&gt; already defined instead of inventing its own formula;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;generated the project&lt;/strong&gt;: page, seven visuals, layout, connection;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;validated it&lt;/strong&gt; against Power BI's schemas and the model before writing anything to disk;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;wrote the files&lt;/strong&gt; and checked the 2025 numbers with one query against the server.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;3 minutes 28 seconds, 30 tool calls.&lt;/strong&gt; One hiccup: on Windows, its first attempt to write all files in one long shell command failed. It noticed, checked that nothing had been written, and wrote the 18 files one by one.&lt;/p&gt;

&lt;p&gt;The result is an ordinary Power BI project folder: a &lt;code&gt;.pbip&lt;/code&gt; file and a definition folder with one JSON file per page and visual. Every file is exactly what the generator produced; the agent didn't hand-edit anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Open it in Power BI Desktop
&lt;/h2&gt;

&lt;p&gt;Double-click the &lt;code&gt;.pbip&lt;/code&gt; file. No preview settings to switch on, no sign-in: Power BI connects live to the demo, and every visual sends a query when it renders.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4jfgr9lsnbbn4xbep3tg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4jfgr9lsnbbn4xbep3tg.png" alt="Data source settings: a live connection to https://demo.emondrian.com/xmla, database OnTime" width="577" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fypwpv7kbf4ztdjk3xy61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fypwpv7kbf4ztdjk3xy61.png" alt="The report as generated: 2025, all carriers" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few things the generator decided, the way a person would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The year slicer opens on &lt;strong&gt;2025&lt;/strong&gt;, the latest &lt;em&gt;complete&lt;/em&gt; year. 2026 is in the list, but it only has seven months.&lt;/li&gt;
&lt;li&gt;The cards show the exact number, &lt;strong&gt;7,001,619&lt;/strong&gt;, not "7M".&lt;/li&gt;
&lt;li&gt;The year line ignores the year slicer, so it keeps all years instead of collapsing to a single point. The carriers bar likewise ignores the carrier slicer, so you still see the ranking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now pick &lt;strong&gt;DL&lt;/strong&gt; (Delta) in the carrier slicer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F11fwjyc8bks3ygtnwfl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F11fwjyc8bks3ygtnwfl5.png" alt="2025 and Delta selected" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The numbers are the same as in last week's Claude dashboard on the same model: &lt;strong&gt;7,001,619 flights in 2025, on-time rate 76.34%; Delta 1,026,332 flights, 79.12%.&lt;/strong&gt; That's the point of a semantic layer: Excel, Power BI and the AI agent get the same measure, defined once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Ask for a change (2½ minutes)
&lt;/h2&gt;

&lt;p&gt;Leave Power BI Desktop open, and in the same Claude Code session:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add a chart with cancellation rate by day of week for the selected year and carrier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent noticed that Power BI Desktop was running. Before writing, it asked me to save any edits there, because Desktop's next save would overwrite its files. Then it added the chart, laid the page out again in two rows so the year line keeps its width, and validated the report. &lt;strong&gt;2 minutes 29 seconds including my answer, 11 tool calls, no errors.&lt;/strong&gt; It changed the positions of three charts and added one file; nothing else.&lt;/p&gt;

&lt;p&gt;Desktop notices the change by itself:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm48ayjk83xz27f2m0xct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm48ayjk83xz27f2m0xct.png" alt="Power BI Desktop: " width="800" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5. Look at the change
&lt;/h2&gt;

&lt;p&gt;Click &lt;strong&gt;Apply external changes&lt;/strong&gt;. The page reloads with the new chart, without reopening the report:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9izn1ethsw9henb8xe1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9izn1ethsw9henb8xe1d.png" alt="The new chart: cancellation rate by day of week, 2025, Delta" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In 2025, across all carriers, Sunday had the highest cancellation rate, 1.73%, and Tuesday the lowest, 1.18%. Delta was different: Friday was its worst day, 1.73%, and Wednesday the best, 0.49%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing this on your own data
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Run eMondrian Community next to your database: &lt;code&gt;git clone https://github.com/eMondrian/emondrian-community&lt;/code&gt; and &lt;code&gt;./setup.sh&lt;/code&gt;. It works with ClickHouse, PostgreSQL, MySQL or any JDBC source.&lt;/li&gt;
&lt;li&gt;Describe your cubes and measures. You can ask Claude to draft the schema over MCP; it validates and saves it.&lt;/li&gt;
&lt;li&gt;Ask for a report, exactly as above, with your server's address instead of the demo's. The agent works from the model, so it never needs your raw tables.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Power BI and AI modules need a key; a free 30-day evaluation key is at &lt;a href="https://emondrian.com/license?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=claude-powerbi" rel="noopener noreferrer"&gt;emondrian.com/license&lt;/a&gt;. Community's MCP server has no sign-in, so keep it on your own machine or a trusted network.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;eMondrian:&lt;/strong&gt; &lt;a href="https://emondrian.com/demo?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=claude-powerbi" rel="noopener noreferrer"&gt;Demo&lt;/a&gt; · &lt;a href="https://github.com/eMondrian/emondrian-community" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://docs.emondrian.com" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; &lt;a href="https://learn.microsoft.com/power-bi/developer/projects/projects-overview" rel="noopener noreferrer"&gt;Power BI Desktop projects (PBIP)&lt;/a&gt; · &lt;a href="https://learn.microsoft.com/power-bi/developer/projects/projects-report" rel="noopener noreferrer"&gt;PBIR report format&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions, or a report you built this way? Leave a comment.&lt;/p&gt;

</description>
      <category>powerbi</category>
      <category>claude</category>
      <category>clickhouse</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Claude Dashboards on ClickHouse, through a semantic layer: a 10-minute tutorial</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Fri, 23 Oct 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/claude-dashboards-on-clickhouse-through-a-semantic-layer-a-10-minute-tutorial-2ami</link>
      <guid>https://dev.to/sergeisemenkov/claude-dashboards-on-clickhouse-through-a-semantic-layer-a-10-minute-tutorial-2ami</guid>
      <description>&lt;p&gt;&lt;em&gt;As of October 2026. You need a paid Claude plan (Pro, Max, Team or Enterprise); on Enterprise an owner has to turn Dashboards on.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On Tuesday I wrote about &lt;a href="https://dev.to/sergeisemenkov/is-your-data-safe-with-claude-dashboards-3cog"&gt;where the data goes when you use Claude Dashboards&lt;/a&gt;. Several people asked for the practical part: how do you actually get a live dashboard on a big ClickHouse table, and what does Claude do along the way?&lt;/p&gt;

&lt;p&gt;Here it is, on the public eMondrian demo: 182 million US flights in ClickHouse, behind a semantic layer that defines measures like &lt;em&gt;On-Time Rate&lt;/em&gt; once. Nothing to install. It took me about ten minutes, most of it reading what Claude was doing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I'm the author of eMondrian, the open-source semantic layer used here.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not connect Claude to ClickHouse directly?&lt;/strong&gt; You can: Claude Dashboards has its own ClickHouse connector. Then Claude writes SQL against your tables, and every table the connection can read is in play. Here the connection goes through a semantic layer instead. Claude sees cubes and measures that are already defined, such as &lt;em&gt;On-Time Rate&lt;/em&gt;, writes MDX against them, and the server generates the SQL. You get the same numbers as in Excel and Power BI, and Claude reaches less of your database. More on that trade-off in &lt;a href="https://dev.to/sergeisemenkov/is-your-data-safe-with-claude-dashboards-3cog"&gt;Is your data safe with Claude Dashboards?&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll build
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe03xef9fn9mkc6etoy01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe03xef9fn9mkc6etoy01.png" alt="The finished Claude Dashboard with Delta selected: slicers, KPI cards, on-time rate by year and by month, the largest carriers" width="800" height="963"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Year and carrier slicers&lt;/li&gt;
&lt;li&gt;KPI cards: on-time rate and flights for the selection&lt;/li&gt;
&lt;li&gt;On-time rate by year (1987–2026) and by month for the selected year&lt;/li&gt;
&lt;li&gt;The largest carriers, with on-time rate on each bar&lt;/li&gt;
&lt;li&gt;A panel with the exact MDX query behind each chart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claude designs the page on every run, so yours will look a little different. The numbers won't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Add the connector (1 minute)
&lt;/h2&gt;

&lt;p&gt;In claude.ai open &lt;strong&gt;Customize → Connectors&lt;/strong&gt;, click &lt;strong&gt;+ Add → Add custom connector&lt;/strong&gt; and fill in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; eMondrian demo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP server URL:&lt;/strong&gt; &lt;code&gt;https://demo.emondrian.com/emondrian/mcp&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxckvm0f09g0wia1ngps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxckvm0f09g0wia1ngps.png" alt="Adding the eMondrian demo as a custom connector" width="539" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Continue&lt;/strong&gt;. Claude checks the server; the demo needs no sign-in, so the connector is added right away. The demo's data is read-only and public, so that's fine here. For your own data it isn't — more on that at the end.&lt;/p&gt;

&lt;p&gt;Open the connector to see its tools. For each one you choose whether Claude may use it always, only with your approval, or never:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu9b3ia68136s4lzxq5rw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu9b3ia68136s4lzxq5rw.png" alt="Tool permissions for the eMondrian demo connector" width="800" height="697"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Start a dashboard (30 seconds)
&lt;/h2&gt;

&lt;p&gt;Open &lt;strong&gt;Artifacts&lt;/strong&gt; and pick &lt;strong&gt;Dashboard (Beta)&lt;/strong&gt;. You get an empty dashboard and a chat next to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb763b5nfailhpo2wuu5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb763b5nfailhpo2wuu5k.png" alt="Artifacts → Dashboard (Beta): an empty dashboard and the prompt" width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Ask for it (1 minute)
&lt;/h2&gt;

&lt;p&gt;Paste this prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using the eMondrian demo connector, build a dashboard for the OnTime cube: on-time rate by year, by month for 2025, and the largest carriers, with year and carrier slicers. Add a panel that shows the MDX each chart sends.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Be specific about measures and the cube. "Build me a flights dashboard" works too, but you'll spend the saved minute on corrections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Watch and approve (5 minutes)
&lt;/h2&gt;

&lt;p&gt;Claude first reads the model, then tests each query before it writes the page. Every tool call asks for your approval, and the approval shows what will run:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;List catalogs&lt;/strong&gt; — which models and cubes the server has.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get schema&lt;/strong&gt; — dimensions, measures and their formulas. This is how Claude learns that &lt;em&gt;On-Time Rate&lt;/em&gt; already exists and how it's defined, instead of inventing its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute query&lt;/strong&gt; — a few MDX test queries, one per chart shape.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwevs90s9yem9j2unmjyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwevs90s9yem9j2unmjyq.png" alt="The approval dialog shows the MDX query before it runs" width="375" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;Allow once&lt;/strong&gt; if you want to read each query. Claude tests about ten of them, and the finished page asks again for each chart when it first loads, so once you've seen enough, click &lt;strong&gt;Always allow&lt;/strong&gt; for &lt;em&gt;Execute query&lt;/em&gt;. Without waiting on me, the build takes well under ten minutes.&lt;/p&gt;

&lt;p&gt;A detail I liked: Claude checked how the slicers would substitute values into the queries, tested them with fixed values, and told me which part it couldn't test from the chat.&lt;/p&gt;

&lt;p&gt;When the page opens for the first time, it shows a consent dialog, &lt;strong&gt;This artifact uses connectors&lt;/strong&gt;, listing the eMondrian demo connector with a switch. Every viewer sees it before the page can query anything. The label says "Can read and make changes"; in practice the page calls one tool, &lt;em&gt;Execute query&lt;/em&gt;, which only reads data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5. Use it
&lt;/h2&gt;

&lt;p&gt;The dashboard is live: each chart is a stored query, not a picture of numbers. Pick another year or a carrier (or click a carrier's bar) and the charts re-query the server. The screenshot at the top shows Delta selected.&lt;/p&gt;

&lt;p&gt;The numbers come from the semantic layer, so they match what Excel and Power BI show for the same model: 7,001,619 flights in 2025 with an on-time rate of 76.3%; for Delta, 1,026,332 flights and 79.1%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6. Look at the MDX
&lt;/h2&gt;

&lt;p&gt;Scroll to the MDX panel. Every chart shows the query it sends, with the current slicer values filled in:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqtb258n8ir598n4yphys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqtb258n8ir598n4yphys.png" alt="The MDX panel: the exact query behind each chart, and how many rows came back" width="800" height="756"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="n"&gt;Measures&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Flights&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Measures&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;Time&lt;/span&gt; &lt;span class="n"&gt;Rate&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;COLUMNS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;NON&lt;/span&gt; &lt;span class="n"&gt;EMPTY&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="nb"&gt;Year&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Members&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;ROWS&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;OnTime&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrToMember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"[Airline].["&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'DL'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;"]"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer is 30 rows: one per year Delta flew. The month chart is 12 rows.&lt;/p&gt;

&lt;p&gt;This is the part I'd show a colleague who asks "where do these numbers come from". It's also what makes the security story simple: the page stores queries, and each one asks the server for a handful of aggregated rows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7. Change it by asking
&lt;/h2&gt;

&lt;p&gt;Ask in the chat, for example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add a chart with cancellation rate by day of week for the selected year and carrier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude tested the new query, found the &lt;em&gt;Cancellation Rate&lt;/em&gt; measure already defined in the model instead of computing its own, and added the chart in under a minute.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rwq62obvex4h5dwwb7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rwq62obvex4h5dwwb7k.png" alt="The new chart after one more prompt" width="800" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8. Share it — with a catch
&lt;/h2&gt;

&lt;p&gt;Dashboards start private. When you share one, each viewer runs the queries &lt;strong&gt;through their own connector&lt;/strong&gt;, so they need the eMondrian demo connector too. A dashboard that uses connectors can't be opened with "Anyone with the link".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7mmilou6lxsld5yer02h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7mmilou6lxsld5yer02h.png" alt="Sharing: private by default" width="437" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happened (30-second version)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Claude saw the &lt;strong&gt;model&lt;/strong&gt; — cubes, measures, formulas. No raw rows.&lt;/li&gt;
&lt;li&gt;The page stores &lt;strong&gt;queries&lt;/strong&gt;. Every time someone opens it, the queries go from the browser through Anthropic's connector service to the eMondrian server, and only &lt;strong&gt;aggregates&lt;/strong&gt; come back (a year by month is 12 rows).&lt;/li&gt;
&lt;li&gt;So the numbers pass through Anthropic's cloud. On the public demo that doesn't matter. For your own data, read &lt;a href="https://dev.to/sergeisemenkov/is-your-data-safe-with-claude-dashboards-3cog"&gt;Is your data safe with Claude Dashboards?&lt;/a&gt; first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Doing this on your own data
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Run eMondrian Community next to your database: &lt;code&gt;git clone https://github.com/eMondrian/emondrian-community&lt;/code&gt; and &lt;code&gt;./setup.sh&lt;/code&gt;. It ships with ClickHouse and an OnTime sample.&lt;/li&gt;
&lt;li&gt;Define your cubes and measures. You can ask Claude Code to draft the schema over MCP; it validates and saves it for you.&lt;/li&gt;
&lt;li&gt;Connect Claude to your server. Two honest caveats:

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;remote connector&lt;/strong&gt; (as above) calls your server from Anthropic's cloud, so the server has to be reachable from the internet. Community's MCP has no sign-in — don't expose it with real data.&lt;/li&gt;
&lt;li&gt;For local testing, use Claude Desktop or Claude Code with a local MCP server instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Power BI and AI modules need a key; a free 30-day evaluation key is at &lt;a href="https://emondrian.com/license?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=claude-dashboard-tutorial" rel="noopener noreferrer"&gt;emondrian.com/license&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;eMondrian:&lt;/strong&gt; &lt;a href="https://emondrian.com/demo?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=claude-dashboard-tutorial" rel="noopener noreferrer"&gt;Demo&lt;/a&gt; · &lt;a href="https://github.com/eMondrian/emondrian-community" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://docs.emondrian.com" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; &lt;a href="https://support.claude.com/en/articles/17454700-get-started-with-claude-dashboards" rel="noopener noreferrer"&gt;Get started with Claude Dashboards&lt;/a&gt; · &lt;a href="https://support.claude.com/en/articles/16994751-artifacts-admin-guide-for-team-and-enterprise-plans" rel="noopener noreferrer"&gt;Artifacts admin guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions, or a dashboard you built on the demo? Leave a comment.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>clickhouse</category>
      <category>mcp</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Is your data safe with Claude Dashboards?</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Tue, 20 Oct 2026 07:30:49 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/is-your-data-safe-with-claude-dashboards-3cog</link>
      <guid>https://dev.to/sergeisemenkov/is-your-data-safe-with-claude-dashboards-3cog</guid>
      <description>&lt;p&gt;&lt;em&gt;What Claude sees, where the data goes, and how a semantic layer on ClickHouse limits it. As of October 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With Claude Dashboards (beta since October 8, 2026), Claude builds a live dashboard for you: you ask a question, it writes the page, and the page keeps querying your data every time someone opens it. I built several of these on an eMondrian semantic layer over 182 million US flight records in ClickHouse, and the first question everyone asked me was the obvious one: &lt;strong&gt;where does the data go?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; Claude sees your &lt;em&gt;model&lt;/em&gt; (table names, measures, formulas), not your rows. Every time the dashboard opens, its queries go through Anthropic's cloud to your semantic layer server, and the aggregated results come back the same way. Whether that's acceptable depends on two things you control: which Claude plan you're on, and where your server sits.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I'm the author of eMondrian, the open-source semantic layer used in this example.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8icl5gqfhpn54ovnowel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8icl5gqfhpn54ovnowel.png" alt="Metadata flows once when Claude builds the dashboard; data flows every time the dashboard opens, through Anthropic's connector service to eMondrian and ClickHouse; only aggregates return" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What actually moves
&lt;/h2&gt;

&lt;p&gt;There are two different flows, and it helps to keep them apart.&lt;/p&gt;

&lt;h3&gt;
  
  
  Metadata: once, when Claude builds the dashboard
&lt;/h3&gt;

&lt;p&gt;To write a dashboard, Claude needs to know what it can ask for. It calls two tools on the eMondrian MCP server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;list_catalogs&lt;/code&gt; returns the models and their cubes:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  OnTime: OnTime (attributes)
  FoodMart: Sales, Warehouse, Store, HR, Sales Ragged, Warehouse and Sales
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;get_schema&lt;/code&gt; returns the model definition: dimensions (Time, Airline, Day of Week, Distance Group), measures, and their formulas:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;CalculatedMember&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"On-Time Rate"&lt;/span&gt; &lt;span class="na"&gt;dimension=&lt;/span&gt;&lt;span class="s"&gt;"Measures"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Formula&amp;gt;&lt;/span&gt;1 - ([Measures].[Late Arrivals] + [Measures].[Cancelled]
                + [Measures].[Diverted]) / [Measures].[Flights]&lt;span class="nt"&gt;&amp;lt;/Formula&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/CalculatedMember&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's metadata. &lt;strong&gt;No data rows are involved.&lt;/strong&gt; One thing to know, though: the schema includes the SQL behind the cube, so table and column names in your database become visible to Claude.&lt;/p&gt;

&lt;p&gt;Claude then writes MDX queries into the page, for example "On-Time Rate and Cancellation Rate for each month of 2025, for Delta". &lt;strong&gt;The page stores queries, not numbers.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Data: every time someone opens the dashboard
&lt;/h3&gt;

&lt;p&gt;When someone opens the page, it runs its stored queries through that person's connector. The request goes from the browser to Anthropic's connector service, then to your eMondrian server. eMondrian turns MDX into SQL, ClickHouse does the aggregation, and the result goes back the same way.&lt;/p&gt;

&lt;p&gt;What comes back is small. The monthly chart for one year is &lt;strong&gt;12 rows × 3 measures&lt;/strong&gt;, not the 7 million flights behind them. Raw rows never leave ClickHouse, because the semantic layer only answers questions about the measures it defines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjo36tiappyjzthvp8zo0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjo36tiappyjzthvp8zo0.png" alt="A Claude Dashboard on the eMondrian demo: year and carrier filters, five KPI cards, on-time rate by year and by month for 2025, and the largest carriers. Each chart is one small aggregated query" width="800" height="755"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A Claude Dashboard built on the eMondrian demo with the prompt from "Try it" below. Every chart is a stored MDX query; the month chart comes back as 12 rows.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Refreshing the dashboard runs the stored queries again. It doesn't ask Claude to write anything new.&lt;/p&gt;

&lt;h3&gt;
  
  
  So, is it safe?
&lt;/h3&gt;

&lt;p&gt;The question isn't whether Claude sees your rows. It's where your numbers travel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The data path goes through Anthropic's cloud.&lt;/strong&gt; This is the main point. Every time anyone opens the dashboard, its queries and their results pass through Anthropic's connector service. The results are small and aggregated, but they are your data, so what happens to them is governed by your agreement with Anthropic (section 2).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your server has to be reachable from Anthropic's cloud.&lt;/strong&gt; That follows from the first point, and it brings its own requirement: a server reachable from the internet needs authentication, or anyone who finds the URL can query it (section 3).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. What Anthropic commits to
&lt;/h2&gt;

&lt;p&gt;Everything below comes from Anthropic's own documentation as of October 2026. Terms change, so check the linked pages before you rely on them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connections come from Anthropic's cloud, not from your laptop.&lt;/strong&gt; The Help Center states that Claude connects to a remote MCP server &lt;em&gt;"from Anthropic's cloud infrastructure, rather than from your local device"&lt;/em&gt;, and that the server &lt;em&gt;"must be reachable over the public internet from Anthropic's IP ranges"&lt;/em&gt;. This applies in the browser and in Claude Desktop alike.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You choose how people sign in to your connector.&lt;/strong&gt; There are three modes: sign in up front, sign in when the server asks, or no sign-in. The documentation is explicit about the last one: with no sign-in, &lt;em&gt;"anyone with access to the server URL can use the connector"&lt;/em&gt;. Connector credentials are stored encrypted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom connectors are unverified.&lt;/strong&gt; Anthropic warns that custom connectors connect Claude to services &lt;em&gt;"that have not been verified by Anthropic"&lt;/em&gt; and that a malicious server could try prompt injection. That's a reason to run your own server rather than someone else's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No training on your content on commercial plans.&lt;/strong&gt; Anthropic's Commercial Terms, which cover the API, Claude Team and Claude Enterprise, say: &lt;em&gt;"Anthropic may not train models on Customer Content from Services."&lt;/em&gt; Personal plans (Free, Pro, Max) are under the consumer terms instead, where it depends on your privacy settings. &lt;strong&gt;If your company's data is involved, use a Team or Enterprise plan.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retention is set by your agreement, not by the terms page.&lt;/strong&gt; The Commercial Terms bring in a Data Processing Addendum and treat your content as your confidential information. Retention periods aren't stated on the terms page itself. If retention matters to you, ask Anthropic for the numbers for your plan in writing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regulated data.&lt;/strong&gt; Anthropic's admin guide says organizations set up for HIPAA (the US health privacy law) can turn Dashboards on, but Dashboards aren't covered by the BAA (Business Associate Agreement, the contract under which Anthropic may handle patient data). So keep PHI (protected health information, i.e. patient data) out of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Private networks: MCP tunnels (Claude Enterprise, research preview).&lt;/strong&gt; If your server must not be reachable from the internet, Claude Enterprise can reach it through an &lt;em&gt;MCP tunnel&lt;/em&gt;. You run a small stack inside your network, and it opens an outbound-only connection, so you need no inbound firewall rules. Cloudflare carries the traffic encrypted and can't read it. Anthropic's backend does terminate it, so Anthropic still processes the content. The tunnel requires MCP servers that use Streamable HTTP and require OAuth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dashboards themselves.&lt;/strong&gt; Claude Dashboards is in beta on Pro, Max, Team and Enterprise plans; on Enterprise it stays off until an owner turns it on. While Claude builds a dashboard, claude.ai asks you to approve each tool call, and the approval shows the exact MDX query it's about to run. The finished dashboard stores its queries and runs them through each viewer's own connector whenever it's opened, refreshed or filtered, so a viewer needs access to that connector. Dashboards start private to you. Sharing outside your organization is an admin setting, and a dashboard that uses connected apps can't be shared with "Anyone with the link". Admins can turn connectors in artifacts on or off, but they can't restrict which connectors a dashboard calls. So the real boundary is the connector itself: what your server lets it see.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. What you control
&lt;/h2&gt;

&lt;p&gt;This is where the real decisions are, and where a semantic layer earns its place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the agent can see at all.&lt;/strong&gt; Claude Dashboards can also connect straight to a warehouse, ClickHouse included. Then Claude writes SQL against your tables, and every table the connection can read is in play. Through a semantic layer it's different: Claude doesn't get a SQL console to your warehouse. It gets the cubes, measures and dimensions you defined, and it writes MDX against them. A table that isn't in a cube isn't reachable through MCP, and an agent can't invent its own "revenue" formula when one is already defined. One caveat: if the server allows the agent to save schemas, the agent could define a new cube over another table. Read-only mode closes that door.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it can do.&lt;/strong&gt; On the public demo, data and schemas are read-only. The tools that change schemas or register catalogs are switched off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who can see which numbers.&lt;/strong&gt; Mondrian roles can restrict access to cubes, dimension members and measures. To tie those roles to the person who signed in, the MCP server needs OAuth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The honest part about eMondrian today:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OAuth for MCP is not part of eMondrian Community.&lt;/strong&gt; Without it, the MCP server has no authentication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;eMondrian Community includes tools that can change schemas.&lt;/strong&gt; Keep its MCP endpoint on &lt;code&gt;localhost&lt;/code&gt; or a trusted network. &lt;strong&gt;Don't expose it to the internet with real data&lt;/strong&gt;: with no sign-in, anyone with the URL could query your cubes.&lt;/li&gt;
&lt;li&gt;There is no audit log of agent queries in Community either.&lt;/li&gt;
&lt;li&gt;Planning a production setup with real data? Contact us at &lt;a href="mailto:contact@bisolutions.dev"&gt;contact@bisolutions.dev&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where your server sits.&lt;/strong&gt; This is the choice that matters most:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Server reachable from&lt;/th&gt;
&lt;th&gt;Fits when&lt;/th&gt;
&lt;th&gt;What you need&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Remote connector&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Anthropic's cloud (internet or allowlisted Anthropic IPs)&lt;/td&gt;
&lt;td&gt;Your company uses Claude Team or Enterprise and allows aggregated data to go through it&lt;/td&gt;
&lt;td&gt;OAuth on the MCP server (not in eMondrian Community)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MCP tunnel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Only your network; outbound connection to Anthropic&lt;/td&gt;
&lt;td&gt;Same, but security policy forbids public endpoints&lt;/td&gt;
&lt;td&gt;Claude Enterprise with tunnels enabled, Streamable HTTP and OAuth on the server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Only your machine or network&lt;/td&gt;
&lt;td&gt;Data must not go to a cloud AI at all&lt;/td&gt;
&lt;td&gt;Claude Desktop with a local MCP server, or any MCP client with a self-hosted model. eMondrian's MCP is a standard server and isn't tied to Claude&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Try it on the public demo
&lt;/h2&gt;

&lt;p&gt;You can see all of this on the public demo. The data is public and read-only.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In claude.ai, open &lt;strong&gt;Customize → Connectors&lt;/strong&gt; and add a custom connector with the URL &lt;code&gt;https://demo.emondrian.com/emondrian/mcp&lt;/code&gt;, then click &lt;strong&gt;Continue&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;Artifacts → Dashboard (Beta)&lt;/strong&gt; and ask: &lt;em&gt;"Using the eMondrian demo connector, build a dashboard for the OnTime cube: on-time rate by year, by month for 2025, and the largest carriers, with year and carrier slicers. Add a panel that shows the MDX each chart sends."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Approve the tool calls as Claude works; each approval shows the query. It took about five minutes for me.&lt;/li&gt;
&lt;li&gt;On the finished dashboard, the MDX panel shows exactly what each chart sends to the server.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step by step, with screenshots: &lt;a href="https://dev.to/sergeisemenkov/claude-dashboards-on-clickhouse-through-a-semantic-layer-a-10-minute-tutorial-2ami"&gt;Claude Dashboards on ClickHouse, through a semantic layer&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources (official):&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://support.claude.com/en/articles/17454700-get-started-with-claude-dashboards" rel="noopener noreferrer"&gt;Get started with Claude Dashboards&lt;/a&gt; ·&lt;br&gt;
&lt;a href="https://support.claude.com/en/articles/16994751-artifacts-admin-guide-for-team-and-enterprise-plans" rel="noopener noreferrer"&gt;Artifacts admin guide&lt;/a&gt; ·&lt;br&gt;
&lt;a href="https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp" rel="noopener noreferrer"&gt;Custom connectors using remote MCP&lt;/a&gt; ·&lt;br&gt;
&lt;a href="https://claude.com/docs/connectors/custom/remote-mcp" rel="noopener noreferrer"&gt;Add a connector that isn't in the directory&lt;/a&gt; ·&lt;br&gt;
&lt;a href="https://claude.com/docs/connectors/mcp-tunnels/overview" rel="noopener noreferrer"&gt;MCP tunnels&lt;/a&gt; ·&lt;br&gt;
&lt;a href="https://www.anthropic.com/legal/commercial-terms" rel="noopener noreferrer"&gt;Anthropic Commercial Terms&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;eMondrian:&lt;/strong&gt; &lt;a href="https://emondrian.com/demo?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=claude-dashboards" rel="noopener noreferrer"&gt;Demo&lt;/a&gt; · &lt;a href="https://github.com/eMondrian/emondrian-community" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://emondrian.com/pricing?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=claude-dashboards" rel="noopener noreferrer"&gt;Pricing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about your own setup? Leave a comment, or write to &lt;a href="mailto:contact@bisolutions.dev"&gt;contact@bisolutions.dev&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>clickhouse</category>
      <category>mcp</category>
    </item>
    <item>
      <title>The new eMondrian: Power BI and AI agents on your own semantic model</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Tue, 13 Oct 2026 07:34:31 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/the-new-emondrian-power-bi-and-ai-agents-on-your-own-semantic-model-4nap</link>
      <guid>https://dev.to/sergeisemenkov/the-new-emondrian-power-bi-and-ai-agents-on-your-own-semantic-model-4nap</guid>
      <description>&lt;p&gt;In 2021 I wrote here &lt;a href="https://dev.to/sergeisemenkov/how-to-load-data-from-mondrian-to-power-bi-desktop-50kb"&gt;how to load data from Mondrian into Power BI Desktop&lt;/a&gt;. The short version of that article was: a &lt;strong&gt;live connection isn't possible&lt;/strong&gt;, so you have to import data with an MDX query.&lt;/p&gt;

&lt;p&gt;That's no longer true. eMondrian now connects to Power BI live — and to AI agents too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Power BI&lt;/strong&gt; connects live to eMondrian through the DAX module — no data import, no SSAS. Your data stays in ClickHouse or your SQL database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI agents&lt;/strong&gt; connect through MCP — they list catalogs, read the semantic model, run queries and can even draft new cubes for you.&lt;/li&gt;
&lt;li&gt;One semantic model, defined once, serves &lt;strong&gt;Excel, Power BI and AI agents&lt;/strong&gt; with the same measures and the same numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can try all three on the &lt;a href="https://emondrian.com/demo?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;public demo&lt;/a&gt; in two minutes, or &lt;a href="https://emondrian.com/get-started?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;install Community&lt;/a&gt; and evaluate DAX and MCP for 30 days with a free key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foxwqjes6mvtbdp6jd2jt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foxwqjes6mvtbdp6jd2jt.png" alt="Excel, Power BI and AI agents connect to one eMondrian semantic model, which queries ClickHouse, PostgreSQL or another JDBC database" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;eMondrian is built on &lt;a href="https://en.wikipedia.org/wiki/Mondrian_OLAP_server" rel="noopener noreferrer"&gt;Mondrian&lt;/a&gt;, the open-source OLAP engine. You describe your business model once — cubes, dimensions, hierarchies, measures like &lt;em&gt;Revenue&lt;/em&gt; or &lt;em&gt;On-Time Rate&lt;/em&gt; — and eMondrian turns every question into SQL against your database.&lt;/p&gt;

&lt;p&gt;Excel has always worked well with this: PivotTables speak &lt;strong&gt;MDX&lt;/strong&gt; over &lt;strong&gt;XMLA&lt;/strong&gt;, the same protocol Microsoft Analysis Services uses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Power BI was the missing piece.&lt;/strong&gt; When Power BI connects live to an Analysis Services–style server, it doesn't send MDX — it sends &lt;strong&gt;DAX&lt;/strong&gt;. Classic Mondrian doesn't understand DAX, so Power BI couldn't use Mondrian cubes live. Teams imported data into Power BI and re-created every measure there — exactly the duplication a semantic layer is supposed to remove.&lt;/p&gt;

&lt;p&gt;At the same time a new kind of client appeared: &lt;strong&gt;AI agents&lt;/strong&gt;. Pointed at raw tables, an agent has to guess joins and formulas, and two agents (or an agent and a report) easily disagree on what "revenue" means. Pointed at a semantic model, the agent uses the definitions your business already agreed on.&lt;/p&gt;

&lt;p&gt;The new eMondrian addresses both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power BI: live connection through the DAX module
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What you get&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Power BI Desktop: &lt;strong&gt;Get data → Analysis Services&lt;/strong&gt;, server &lt;code&gt;http://&amp;lt;your-server&amp;gt;/xmla&lt;/code&gt;, &lt;strong&gt;Connect live&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Your cubes appear as a Power BI semantic model: measures, dimensions and hierarchies, ready to drag into visuals.&lt;/li&gt;
&lt;li&gt;Every visual sends a DAX query to eMondrian; eMondrian evaluates it against the model and sends SQL to your database. Nothing is imported into Power BI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frud9ms0dfz00r65kq31u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frud9ms0dfz00r65kq31u.png" alt="A Power BI visual sends DAX over XMLA to the eMondrian DAX module, which maps it to the cube model; the engine sends SQL to ClickHouse" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The DAX module evaluates the queries Power BI sends on the same engine that serves MDX — so a measure defined once in the schema gives the same result in Excel and in Power BI.&lt;/p&gt;

&lt;p&gt;You can see exactly what Power BI sends: in Power BI Desktop open &lt;strong&gt;Performance analyzer&lt;/strong&gt;, refresh a visual and copy its DAX query. A simple example on the FoodMart sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EVALUATE ROW("Org_Salary", 'HR'[Org Salary])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why a live connection instead of import or DirectQuery&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No duplicated business logic.&lt;/strong&gt; Measures live in one place — the eMondrian schema — not in every Power BI file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No data copies.&lt;/strong&gt; Data stays in your database; there's no import refresh to schedule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same numbers in Excel and Power BI.&lt;/strong&gt; Both clients query the same model.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note on Microsoft support.&lt;/strong&gt; Power BI connects to eMondrian through its Analysis Services connector. Microsoft officially supports only a few third-party semantic models, and eMondrian is not one of them. Microsoft support won't help with this setup — eMondrian Enterprise does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  AI agents through MCP
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;MCP&lt;/a&gt; — the Model Context Protocol — is the standard way AI agents such as Claude connect to tools and data. eMondrian now includes an MCP server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc3zry782w3o18s6w39f6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc3zry782w3o18s6w39f6.png" alt="An AI agent talks MCP to eMondrian's tools — list_catalogs, get_schema, execute_query, the authoring guide, validate_schema, save_schema — which query the semantic model" width="799" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What the agent can do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;list_catalogs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;See which catalogs (semantic models) exist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;get_schema&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read a model: cubes, dimensions, measures and their definitions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;execute_query&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run MDX or DAX against a catalog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;get_cube_authoring_guide&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Learn how to write eMondrian schemas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validate_schema&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check a schema for problems before using it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;save_schema&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Save a new or updated schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;save_catalog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Register a new catalog and write its schema file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;read_logs&lt;/code&gt;, &lt;code&gt;get_properties&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Inspect server logs and settings when something goes wrong&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Ask questions in business terms.&lt;/strong&gt; Connect Claude Code in one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; sse emondrian http://localhost/emondrian/mcp/sse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Compare the cancellation rate of American Airlines and Delta in January 2022 and explain the difference.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent reads the OnTime model, finds the &lt;em&gt;Cancellation Rate&lt;/em&gt; measure — already defined as &lt;code&gt;Cancelled / Flights&lt;/code&gt; — writes the MDX, runs it on ClickHouse through eMondrian and explains the answer. It doesn't invent its own formula, so its numbers match your Excel and Power BI reports.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let the agent build your first cube
&lt;/h3&gt;

&lt;p&gt;This is the part I'm most excited about. Describing the first cube has always been the hardest step of an eMondrian evaluation. With MCP, an agent can do most of it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In catalog MySales, create a cube Sales on the ClickHouse table &lt;code&gt;sales&lt;/code&gt; (sale_date, region, product, quantity, amount). Add a Time dimension from sale_date, Region and Product dimensions, measures Amount and Quantity, and Avg Price = Amount / Quantity. Follow the cube authoring guide, validate the schema, then save it.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4i942wfzaif63ohy7kab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4i942wfzaif63ohy7kab.png" alt="The agent reads the authoring guide, drafts the schema, validates it, saves it to the catalog, and the cube opens in Excel or Power BI" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  One model, three clients
&lt;/h2&gt;

&lt;p&gt;The real point isn't Power BI or MCP on their own. It's that &lt;strong&gt;one semantic model now serves all three kinds of clients&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F77srfhnf1pbawxuvimor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F77srfhnf1pbawxuvimor.png" alt="The On-Time Rate measure is defined once in the schema and gives the same number in Excel, Power BI and an AI agent" width="799" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Excel&lt;/th&gt;
&lt;th&gt;Power BI&lt;/th&gt;
&lt;th&gt;AI agents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Protocol&lt;/td&gt;
&lt;td&gt;XMLA / MDX&lt;/td&gt;
&lt;td&gt;XMLA / DAX&lt;/td&gt;
&lt;td&gt;MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use&lt;/td&gt;
&lt;td&gt;PivotTables, ad-hoc analysis&lt;/td&gt;
&lt;td&gt;Dashboards, reports&lt;/td&gt;
&lt;td&gt;Questions in plain language, schema authoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Measures come from&lt;/td&gt;
&lt;td&gt;the eMondrian schema&lt;/td&gt;
&lt;td&gt;the eMondrian schema&lt;/td&gt;
&lt;td&gt;the eMondrian schema&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Define &lt;em&gt;Revenue&lt;/em&gt; once. Finance sees it in Excel, management in Power BI, and the AI assistant uses the same definition when someone asks "how did revenue develop last quarter?".&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7ql0ni82tynhnxx9xd55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7ql0ni82tynhnxx9xd55.png" alt="Four steps: public demo, Community on your machine, your own data, production" width="800" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Public demo — two minutes, nothing to install.&lt;/strong&gt;&lt;br&gt;
Connect Excel or Power BI to &lt;code&gt;https://demo.emondrian.com/xmla&lt;/code&gt; and explore the FoodMart and OnTime (ClickHouse) samples. &lt;a href="https://emondrian.com/demo?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;Demo guide →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents can use the demo too, in read-only mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; sse emondrian-demo https://demo.emondrian.com/emondrian/mcp/sse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Community on your machine — about 15 minutes.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/eMondrian/emondrian-community.git
&lt;span class="nb"&gt;cd &lt;/span&gt;emondrian-community
./setup.sh          &lt;span class="c"&gt;# Windows: powershell -ExecutionPolicy Bypass -File .\windows-setup.ps1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Excel works right away. For Power BI and AI agents, request a free &lt;strong&gt;30-day evaluation key&lt;/strong&gt; — one key unlocks both DAX and MCP. &lt;a href="https://docs.emondrian.com/getting-started/quickstart" rel="noopener noreferrer"&gt;Quickstart →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Your own data.&lt;/strong&gt;&lt;br&gt;
Connect your ClickHouse (or other JDBC) database, describe a cube — by hand or with an agent — and point your real Power BI reports at it. Need more than 30 days? &lt;a href="https://emondrian.com/license?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch#extend" rel="noopener noreferrer"&gt;Ask for an extension&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Licensing at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Community&lt;/th&gt;
&lt;th&gt;Commercial License&lt;/th&gt;
&lt;th&gt;Enterprise&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Engine, XMLA, MDX, Excel&lt;/td&gt;
&lt;td&gt;✓ free, EPL-1.0&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DAX module (Power BI)&lt;/td&gt;
&lt;td&gt;30-day evaluation&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MCP module (AI agents)&lt;/td&gt;
&lt;td&gt;30-day evaluation&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;GitHub issues&lt;/td&gt;
&lt;td&gt;Email&lt;/td&gt;
&lt;td&gt;Priority, help with your DAX reports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;€4,900 per server / year&lt;/td&gt;
&lt;td&gt;On request&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The engine is open source under EPL-1.0. The DAX and MCP modules ship with Community and are unlocked by a license key. &lt;a href="https://emondrian.com/pricing?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;Pricing →&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What to expect — honestly
&lt;/h2&gt;

&lt;p&gt;We're a small team, so I'd rather be clear about the current limits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DAX support for Power BI is in beta.&lt;/strong&gt; Test your own reports during the evaluation and send us the queries that fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not officially supported by Microsoft.&lt;/strong&gt; See the note above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP in Community is for local use.&lt;/strong&gt; The MCP endpoint has no authentication and includes tools that can change schemas and register catalogs. Keep it on &lt;code&gt;localhost&lt;/code&gt; or a trusted network. Authentication, per-user access and an audit log of agent queries are planned for Enterprise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support hours.&lt;/strong&gt; Business days, UTC+4. No 24/7.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More in &lt;a href="https://emondrian.com/what-to-expect?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;What to expect&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://emondrian.com/demo?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;Demo&lt;/a&gt; · &lt;a href="https://docs.emondrian.com/getting-started/quickstart" rel="noopener noreferrer"&gt;Quickstart&lt;/a&gt; · &lt;a href="https://github.com/eMondrian/emondrian-community" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://emondrian.com/license?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;Get an evaluation key&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions or a failing DAX query? Leave a comment here, &lt;a href="https://github.com/eMondrian/emondrian-community/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; or write to &lt;a href="mailto:contact@bisolutions.dev"&gt;contact@bisolutions.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;eMondrian is developed and supported by &lt;a href="https://bisolutions.dev/" rel="noopener noreferrer"&gt;BIS — Business Intelligence Solutions&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>powerbi</category>
      <category>clickhouse</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>Planning in Excel with Writeback</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Mon, 05 Sep 2022 18:26:30 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/planning-in-excel-with-writeback-58gc</link>
      <guid>https://dev.to/sergeisemenkov/planning-in-excel-with-writeback-58gc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2026:&lt;/strong&gt; eMondrian has a new home — &lt;a href="https://emondrian.com" rel="noopener noreferrer"&gt;emondrian.com&lt;/a&gt;, docs at &lt;a href="https://docs.emondrian.com" rel="noopener noreferrer"&gt;docs.emondrian.com&lt;/a&gt;, code at &lt;a href="https://github.com/eMondrian/emondrian-community" rel="noopener noreferrer"&gt;github.com/eMondrian/emondrian-community&lt;/a&gt;. What's new: &lt;a href="https://dev.to/sergeisemenkov/the-new-emondrian-power-bi-and-ai-agents-on-your-own-semantic-model-4nap"&gt;The new eMondrian&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check our newest video on how &lt;a href="https://sergeisemenkov.github.io/eMondrian/" rel="noopener noreferrer"&gt;eMondrian&lt;/a&gt; can support you to decentralize your planning and forecasting activities for your organization.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/kmpBqEFKZWA" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Our example from today is a beverages company which operates in many different regions and has plenty of stores. We are going to quickly show you how you could outsource the initial planning for the sales per product to the store managers.&lt;/p&gt;

&lt;p&gt;This video was created by &lt;a href="https://www.linkedin.com/in/leandro-aeschlimann/" rel="noopener noreferrer"&gt;Leandro Aeschlimann&lt;/a&gt;. His company &lt;a href="https://www.linkedin.com/company/consenso-solutions/" rel="noopener noreferrer"&gt;Consenso&lt;/a&gt; specialises in implementing data analytics tools and data infrastructure.&lt;/p&gt;

&lt;p&gt;eMondrian  is a free and open source alternative to Analysis Services from Microsoft which you can install on Linux and Windows.&lt;br&gt;
It allows you to build cubes and consolidate the tables of you underlying data sources to a data model and connect to it from various client tools to visualize &amp;amp; analyse your data in a more user friendly way.&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>management</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Welcome to the free open-source OLAP server project</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Mon, 15 Nov 2021 13:59:06 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/welcome-to-the-free-open-source-olap-server-project-132f</link>
      <guid>https://dev.to/sergeisemenkov/welcome-to-the-free-open-source-olap-server-project-132f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2026:&lt;/strong&gt; eMondrian has a new home — &lt;a href="https://emondrian.com" rel="noopener noreferrer"&gt;emondrian.com&lt;/a&gt;, docs at &lt;a href="https://docs.emondrian.com" rel="noopener noreferrer"&gt;docs.emondrian.com&lt;/a&gt;, code at &lt;a href="https://github.com/eMondrian/emondrian-community" rel="noopener noreferrer"&gt;github.com/eMondrian/emondrian-community&lt;/a&gt;. What's new: &lt;a href="https://dev.to/sergeisemenkov/the-new-emondrian-power-bi-and-ai-agents-on-your-own-semantic-model-4nap"&gt;The new eMondrian&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Welcome to the site of the &lt;a href="https://sergeisemenkov.github.io/eMondrian" rel="noopener noreferrer"&gt;&lt;strong&gt;eMondrian&lt;/strong&gt;&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;eMondrian is a free open-source &lt;a href="https://en.wikipedia.org/wiki/Online_analytical_processing" rel="noopener noreferrer"&gt;OLAP&lt;/a&gt; server. It is based on the &lt;a href="https://github.com/pentaho/mondrian" rel="noopener noreferrer"&gt;Mondrian&lt;/a&gt; project. OLAP server allows you to represent your database as a multidimensional space with dimensions and measures. It hides the complexity of underlying tables and their relations and allows you to interactively analyze data from multiple perspectives. eMondrian server can run on Windows and Linux operating systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj34edhvspxe64fjrw52k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj34edhvspxe64fjrw52k.png" alt=" " width="799" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;eMondrian supports XML for Analysis (XMLA) standard and OLE DB for OLAP at the level that makes it possible to connect to it from client tools such as Microsoft Excel, Power BI, Tableau and many others. The logic of the original Mondrian was changed in order to improve performance of queries specific to these clients and to support clients’ features, for example Excel’s sessions, calculated members and sets.&lt;/p&gt;

&lt;p&gt;Any database that has a &lt;a href="https://en.wikipedia.org/wiki/JDBC_driver" rel="noopener noreferrer"&gt;JDBC&lt;/a&gt; driver can be the source for eMondrian. eMondrian server is a Relational OLAP (ROLAP) server that means it always shows real time data from a source. This server runs queries written in the MDX language, reads data from a source database and presents results in a multidimensional format.&lt;/p&gt;

&lt;p&gt;The most efficient way is to use &lt;a href="https://en.wikipedia.org/wiki/Column-oriented_DBMS" rel="noopener noreferrer"&gt;column store databases&lt;/a&gt; as data sources for eMondrian. For example, &lt;a href="https://clickhouse.com/" rel="noopener noreferrer"&gt;ClickHouse&lt;/a&gt; could run as a powerful and fast query engine while eMondrian works as a proxy representing data as cubes and executing MDX queries. &lt;/p&gt;

</description>
      <category>analytics</category>
      <category>backend</category>
      <category>database</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A simple way to import data to Power BI from Mondrian</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Sun, 01 Aug 2021 16:22:05 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/a-simple-way-to-import-data-to-power-bi-from-mondrian-52b1</link>
      <guid>https://dev.to/sergeisemenkov/a-simple-way-to-import-data-to-power-bi-from-mondrian-52b1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2026:&lt;/strong&gt; besides importing with MDX, Power BI can now connect to eMondrian &lt;strong&gt;live&lt;/strong&gt;. See &lt;a href="https://dev.to/sergeisemenkov/the-new-emondrian-power-bi-and-ai-agents-on-your-own-semantic-model-4nap"&gt;The new eMondrian: Power BI and AI agents on your own semantic model&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/sergeisemenkov/how-to-load-data-from-mondrian-to-power-bi-desktop-50kb"&gt;previous article&lt;/a&gt; I described how to import data to Power BI using MDX query. A new version of &lt;a href="https://github.com/SergeiSemenkov/eMondrian" rel="noopener noreferrer"&gt;eMondrain&lt;/a&gt; allows you to load data from Mondrian without any query, using only Power BI designer. eMondrain is a version of Mondrian that is modified to support Excel and some other applications as clients.&lt;/p&gt;

&lt;p&gt;As an example, we will load data from the Mondrian sample database Foodmart.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://powerbi.microsoft.com/en-us/desktop/" rel="noopener noreferrer"&gt;Power BI Desktop&lt;/a&gt; application we create a new report and select the menu &lt;strong&gt;Get data&lt;/strong&gt; - &lt;strong&gt;Analysis Services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecnz19o03ha2u4ik373k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecnz19o03ha2u4ik373k.png" alt="Alt Text" width="754" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;SQL Server Analysis Services database&lt;/strong&gt; dialog we fill in the &lt;strong&gt;Server&lt;/strong&gt; field as a connection string to the Mondrian server. Pick the &lt;strong&gt;Import&lt;/strong&gt; radio button and push the &lt;strong&gt;Ok&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;To try this example you can use an online eMondrian server with a sample database. The server address is &lt;em&gt;&lt;a href="https://ssemenkoff.dev/emondrian/xmla" rel="noopener noreferrer"&gt;https://ssemenkoff.dev/emondrian/xmla&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddwbgta4ggsy23tlfkvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddwbgta4ggsy23tlfkvt.png" width="704" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Navigator&lt;/strong&gt; window will appear. There you have to pick up columns that you want to see in your report. While you are choosing columns you will see a data preview on the right side of the window. As you finish push the &lt;strong&gt;Load&lt;/strong&gt; button. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fom894p54k8cxr5b3n3ks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fom894p54k8cxr5b3n3ks.png" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Data will be loaded to our report and available columns will appear on the right side of the application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdmo9cpzthazaszbwqog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdmo9cpzthazaszbwqog.png" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This way of loading data from Mondrian OLAP server to Power BI is very simple and doesn’t need any knowledge of a query language.&lt;/p&gt;

&lt;p&gt;If you have any questions or suggestions, feel free to contact me at &lt;a href="mailto:siarhei.semiankou@gmail.com"&gt;siarhei.semiankou@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>powerbi</category>
      <category>mondrian</category>
      <category>emondrian</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to load data from Mondrian to Power BI Desktop</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Fri, 05 Mar 2021 10:22:52 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/how-to-load-data-from-mondrian-to-power-bi-desktop-50kb</link>
      <guid>https://dev.to/sergeisemenkov/how-to-load-data-from-mondrian-to-power-bi-desktop-50kb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2026:&lt;/strong&gt; Power BI can now connect to eMondrian &lt;strong&gt;live&lt;/strong&gt; — no MDX import needed. eMondrian answers the DAX queries Power BI sends, and AI agents can use the same model over MCP. See &lt;a href="https://dev.to/sergeisemenkov/the-new-emondrian-power-bi-and-ai-agents-on-your-own-semantic-model-4nap"&gt;The new eMondrian: Power BI and AI agents on your own semantic model&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However it’s impossible to explore &lt;a href="https://en.wikipedia.org/wiki/Mondrian_OLAP_server" rel="noopener noreferrer"&gt;Mondrian&lt;/a&gt; cubes in &lt;a href="https://powerbi.microsoft.com/en-us/desktop/" rel="noopener noreferrer"&gt;Power BI Desktop&lt;/a&gt; through live connection, there is a way how you can load data from Mondrian by queries.&lt;/p&gt;

&lt;p&gt;Let’s load data from the Mondrian sample database Foodmart and create a simple interactive report. This example is using the &lt;a href="https://github.com/SergeiSemenkov/eMondrian" rel="noopener noreferrer"&gt;eMondrain&lt;/a&gt; version of Mondrian that is modified to support Excel and some other applications as clients.&lt;/p&gt;

&lt;p&gt;First we have to design a &lt;a href="https://en.wikipedia.org/wiki/MultiDimensional_eXpressions" rel="noopener noreferrer"&gt;MDX&lt;/a&gt; query. Following query gets sales amount data with dates and store information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
[Measures].[Store Sales] on COLUMNS,
CrossJoin( [Time].[Month].Members, [Store].[Store Name].Members ) on ROWS
FROM [Sales]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mondrian server can return data in two formats. First format is CellSet data format which is convenient in case of using client controls like Pivot Table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdphu9ul4umvs6mh29mtr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdphu9ul4umvs6mh29mtr.png" width="612" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second format is tabular format. It’s a simple table and is convenient when you are designing a report with tables and charts. This format is used by Power Bi when it loads data from Mondrian.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1xcm769spbee5jol802.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1xcm769spbee5jol802.png" alt="Alt Text" width="659" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Power BI Desktop application we create a new report and select the menu &lt;strong&gt;Get data&lt;/strong&gt; - &lt;strong&gt;Analysis Services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc1qvegtslwjpe9qlexx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc1qvegtslwjpe9qlexx.png" width="799" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;SQL Server Analysis Services database&lt;/strong&gt; dialog we fill in the &lt;strong&gt;Server&lt;/strong&gt; field as a connection string to the Mondrian server. Fill in database name in field &lt;strong&gt;Database&lt;/strong&gt;. &lt;strong&gt;Database&lt;/strong&gt; is a required field and is case sensitive (in our case it's &lt;em&gt;FoodMart&lt;/em&gt;). Pick the &lt;strong&gt;Import&lt;/strong&gt; radio button. In the &lt;strong&gt;MDX or DAX query (optional)&lt;/strong&gt; field copy our MDX query and push the &lt;strong&gt;Ok&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;To try this example you can use an online eMondrian server with a sample database. The server address is &lt;em&gt;&lt;a href="https://ssemenkoff.dev/emondrian/xmla" rel="noopener noreferrer"&gt;https://ssemenkoff.dev/emondrian/xmla&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8sat1yl3uzjvkg3sqgza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8sat1yl3uzjvkg3sqgza.png" width="705" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Preview window will appear where you can see part of the query result data in tabular format. Click the &lt;strong&gt;Load&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F02fz79g6ag6inadfdj6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F02fz79g6ag6inadfdj6x.png" width="713" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the &lt;strong&gt;Data&lt;/strong&gt; tab, rename columns and change &lt;em&gt;Sales&lt;/em&gt; column data type from &lt;em&gt;Text&lt;/em&gt; to &lt;em&gt;Decimal number&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvowlbfhcle5vg1g9jltu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvowlbfhcle5vg1g9jltu.png" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s return to the &lt;strong&gt;Report&lt;/strong&gt; tab and add some visualizations. In this example we use &lt;em&gt;Slicer&lt;/em&gt;, &lt;em&gt;Pie chart&lt;/em&gt; and &lt;em&gt;Table&lt;/em&gt; controls.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7t5ke9if4k73dpafq1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7t5ke9if4k73dpafq1f.png" width="800" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To refresh your report and load newly added data you can always use the &lt;strong&gt;Refresh&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;As you see, you can add to your Power BI Desktop reports new ones which use data from the Mondrian OLAP server.&lt;/p&gt;

&lt;p&gt;If you have any questions or suggestions, feel free to contact me at &lt;a href="mailto:siarhei.semiankou@gmail.com"&gt;siarhei.semiankou@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>powerbi</category>
      <category>mondrian</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to explore ClickHouse data via Excel PivotTable using Mondrian</title>
      <dc:creator>Sergei Semenkov</dc:creator>
      <pubDate>Wed, 20 Jan 2021 12:39:26 +0000</pubDate>
      <link>https://dev.to/sergeisemenkov/how-to-explore-clickhouse-data-via-excel-pivottable-using-mondrian-4o46</link>
      <guid>https://dev.to/sergeisemenkov/how-to-explore-clickhouse-data-via-excel-pivottable-using-mondrian-4o46</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2026:&lt;/strong&gt; eMondrian now runs with Docker in one command and also works with Power BI and AI agents. Current setup: &lt;a href="https://docs.emondrian.com/getting-started/quickstart" rel="noopener noreferrer"&gt;Quickstart&lt;/a&gt; · What's new: &lt;a href="https://dev.to/sergeisemenkov/the-new-emondrian-power-bi-and-ai-agents-on-your-own-semantic-model-4nap"&gt;The new eMondrian&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ClickHouse is a very powerful OLAP engine. Microsoft Excel is one of the world's most popular and powerful business programs. There are several ways to bring ClickHouse data to Excel spreadsheets.&lt;/p&gt;

&lt;p&gt;One way to do this is using ClickHouse ODBC driver. In order to do this you have to install the ODBC driver and create ClickHouse data source in Excel. Then you can explore data as tables or you can run a query on ClickHouse and browse results.&lt;/p&gt;

&lt;p&gt;The other way to explore ClickHouse data in Excel is using Mondrian. This approach allows you to describe ClickHouse data as a multidimensional model and give access to this model through XMLA standart. It also allows client applications to run MDX queries on ClickHouse data. You represent ClickHouse data as cubes and dimensions and then browse those cubes in Excel PivotTable.&lt;/p&gt;

&lt;p&gt;This article describes how to install Mondrian, create a Mondrian datasource for ClickHouse database and connect Excel PivotTable to this datasource.&lt;/p&gt;

&lt;p&gt;We will use the &lt;a href="https://github.com/SergeiSemenkov/eMondrian" rel="noopener noreferrer"&gt;eMondrian&lt;/a&gt; fork of the Mondrian ROLAP engine. The main feature of this version is support of ADOMD.NET and Excel clients. eMondrian already includes ClickHouse driver.&lt;/p&gt;

&lt;p&gt;Mondrian can be hosted on different java servers (Apache Tomcat, Jetty, Tiny Java Web Server). This example describes the case with Ubuntu operating system and Apache Tomcat java server.&lt;/p&gt;

&lt;p&gt;In this example Tomcat is installed in &lt;code&gt;/opt/tomcat/latest/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;You have to change the following command to your Tomcat path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TOMCATDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/opt/tomcat/latest"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next commands download the Mondrian archive, copy it to Tomcat directory and restart Tomcat java server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;wget https://github.com/SergeiSemenkov/eMondrian/releases/latest/download/emondrian.war
&lt;span class="nb"&gt;sudo cp &lt;/span&gt;emondrian.war &lt;span class="nv"&gt;$TOMCATDIR&lt;/span&gt;/webapps
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart tomcat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's connect Excel to the Mondrian demo Foodmart database.&lt;/p&gt;

&lt;p&gt;In order to get address to your Mondrian XMLA service you have to insert your Ubuntu server ip in following template&lt;br&gt;
&lt;code&gt;http://&amp;lt;your_server_address&amp;gt;:8080/emondrian/xmla&lt;/code&gt;&lt;br&gt;
To get your server ip,  run command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example Mondrian server address is&lt;br&gt;
&lt;code&gt;http://192.168.100.4:8080/emondrian/xmla&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open &lt;strong&gt;Excel&lt;/strong&gt;, select the &lt;strong&gt;Data&lt;/strong&gt; tab, then &lt;strong&gt;Get Data&lt;/strong&gt; -&amp;gt; &lt;strong&gt;From Database&lt;/strong&gt; -&amp;gt; &lt;strong&gt;From Analysis Services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fecmtmq5d6jbzw66lbql9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fecmtmq5d6jbzw66lbql9.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paste address of Mondrian XMLA service as Server name and click Next. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqji4ttmgxzxsbokutspx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqji4ttmgxzxsbokutspx.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then choose a cube and click Finish. The PivotTable with cube data will appear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8jx2ehbj54ro99b9lzno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8jx2ehbj54ro99b9lzno.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we will create a Mondrian schema for ClickHouse example dataset &lt;a href="https://clickhouse.tech/docs/en/getting-started/example-datasets/ontime/" rel="noopener noreferrer"&gt;OnTime&lt;/a&gt;. The schema defines two cubes. Cube OnTime is based on data from ontime table. Cube ViewOnTime is an example of how to create a cube based on a query instead of a table.&lt;/p&gt;

&lt;p&gt;Following command will create new schema file OnTime.xml.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano &lt;span class="nv"&gt;$TOMCATDIR&lt;/span&gt;/webapps/emondrian/WEB-INF/schema/OnTime.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy xml to this file and press &lt;em&gt;Ctrl-S&lt;/em&gt; (Save) and &lt;em&gt;Ctrl-X&lt;/em&gt;(Exit).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Schema&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"OnTime"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Cube&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"OnTime"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Table&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ontime"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Dimension&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Date"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Hierarchy&lt;/span&gt; &lt;span class="na"&gt;hasAll=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;allMemberName=&lt;/span&gt;&lt;span class="s"&gt;"All Dates"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Year"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"Year"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"Numeric"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Quarter"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"Quarter"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"Numeric"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;CaptionExpression&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;SQL&lt;/span&gt; &lt;span class="na"&gt;dialect=&lt;/span&gt;&lt;span class="s"&gt;"generic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;concat(toString(Quarter), ' ', toString(Year))&lt;span class="nt"&gt;&amp;lt;/SQL&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/CaptionExpression&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/Level&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Month"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"Month"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"Numeric"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;CaptionExpression&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;SQL&lt;/span&gt; &lt;span class="na"&gt;dialect=&lt;/span&gt;&lt;span class="s"&gt;"generic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            concat(          
            CASE toString(Month) WHEN '1' THEN 'January'
            WHEN '2' THEN 'February'
            WHEN '3' THEN 'March'
            WHEN '4' THEN 'April'
            WHEN '5' THEN 'May'
            WHEN '6' THEN 'June'
            WHEN '7' THEN 'July'
            WHEN '8' THEN 'August'
            WHEN '9' THEN 'September'
            WHEN '10' THEN 'October'
            WHEN '11' THEN 'November'
            WHEN '12' THEN 'December'
            ELSE 'Unknown' END,
            ' ',
            toString(Year))
          &lt;span class="nt"&gt;&amp;lt;/SQL&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/CaptionExpression&amp;gt;&lt;/span&gt; 
      &lt;span class="nt"&gt;&amp;lt;/Level&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Day"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"FlightDate"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"Date"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;CaptionExpression&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;SQL&lt;/span&gt; &lt;span class="na"&gt;dialect=&lt;/span&gt;&lt;span class="s"&gt;"generic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;concat(toString(Year), '-', toString(Month), '-', toString(DayofMonth))&lt;span class="nt"&gt;&amp;lt;/SQL&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/CaptionExpression&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/Level&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Hierarchy&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Dimension&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Dimension&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Unique Carrier"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Hierarchy&lt;/span&gt; &lt;span class="na"&gt;hasAll=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;allMemberName=&lt;/span&gt;&lt;span class="s"&gt;"All Unique Carriers"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Unique Carrier"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;KeyExpression&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;SQL&lt;/span&gt; &lt;span class="na"&gt;dialect=&lt;/span&gt;&lt;span class="s"&gt;"generic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;toStringCutToZero(UniqueCarrier)&lt;span class="nt"&gt;&amp;lt;/SQL&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/KeyExpression&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/Level&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Hierarchy&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Dimension&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Dimension&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Destination"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Hierarchy&lt;/span&gt; &lt;span class="na"&gt;hasAll=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;allMemberName=&lt;/span&gt;&lt;span class="s"&gt;"All Destinations"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Destination State Name"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"DestStateName"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Destination City"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"DestCityName"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Hierarchy&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Dimension&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Dimension&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Origin"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Hierarchy&lt;/span&gt; &lt;span class="na"&gt;hasAll=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;allMemberName=&lt;/span&gt;&lt;span class="s"&gt;"All Origins"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Origin State Name"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"OriginStateName"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Origin City"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"OriginCityName"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Hierarchy&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Dimension&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Measure&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Flights"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"Flights"&lt;/span&gt; &lt;span class="na"&gt;aggregator=&lt;/span&gt;&lt;span class="s"&gt;"sum"&lt;/span&gt; &lt;span class="na"&gt;formatString=&lt;/span&gt;&lt;span class="s"&gt;"#,###"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Measure&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Air Time"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"AirTime"&lt;/span&gt; &lt;span class="na"&gt;aggregator=&lt;/span&gt;&lt;span class="s"&gt;"sum"&lt;/span&gt; &lt;span class="na"&gt;formatString=&lt;/span&gt;&lt;span class="s"&gt;"#,###"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Measure&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Distance"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"Distance"&lt;/span&gt; &lt;span class="na"&gt;aggregator=&lt;/span&gt;&lt;span class="s"&gt;"sum"&lt;/span&gt; &lt;span class="na"&gt;formatString=&lt;/span&gt;&lt;span class="s"&gt;"#,###"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Measure&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Dep Delay"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"DepDelay"&lt;/span&gt; &lt;span class="na"&gt;aggregator=&lt;/span&gt;&lt;span class="s"&gt;"sum"&lt;/span&gt; &lt;span class="na"&gt;formatString=&lt;/span&gt;&lt;span class="s"&gt;"#,###"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Measure&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Carrier Delay"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"CarrierDelay"&lt;/span&gt; &lt;span class="na"&gt;aggregator=&lt;/span&gt;&lt;span class="s"&gt;"sum"&lt;/span&gt; &lt;span class="na"&gt;formatString=&lt;/span&gt;&lt;span class="s"&gt;"#,###"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Measure&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Weather Delay"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"WeatherDelay"&lt;/span&gt; &lt;span class="na"&gt;aggregator=&lt;/span&gt;&lt;span class="s"&gt;"sum"&lt;/span&gt; &lt;span class="na"&gt;formatString=&lt;/span&gt;&lt;span class="s"&gt;"#,###"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Cube&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Cube&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ViewOnTime"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;View&lt;/span&gt; &lt;span class="na"&gt;alias=&lt;/span&gt;&lt;span class="s"&gt;"ViewOnTime"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;SQL&lt;/span&gt; &lt;span class="na"&gt;dialect=&lt;/span&gt;&lt;span class="s"&gt;"generic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;![CDATA[select * from ontime]]&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/SQL&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/View&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Dimension&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Destination City Name"&lt;/span&gt; &lt;span class="na"&gt;foreignKey=&lt;/span&gt;&lt;span class="s"&gt;"DestCityName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Hierarchy&lt;/span&gt; &lt;span class="na"&gt;hasAll=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;allMemberName=&lt;/span&gt;&lt;span class="s"&gt;"All Destinations"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Destination City Name"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"DestCityName"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Hierarchy&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Dimension&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Dimension&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Origin City Name"&lt;/span&gt; &lt;span class="na"&gt;foreignKey=&lt;/span&gt;&lt;span class="s"&gt;"OriginCityName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Hierarchy&lt;/span&gt; &lt;span class="na"&gt;hasAll=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;allMemberName=&lt;/span&gt;&lt;span class="s"&gt;"All Origin Cities"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Level&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Origin City Name"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"OriginCityName"&lt;/span&gt; &lt;span class="na"&gt;uniqueMembers=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Hierarchy&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Dimension&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Measure&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Dep Delay"&lt;/span&gt; &lt;span class="na"&gt;column=&lt;/span&gt;&lt;span class="s"&gt;"DepDelay"&lt;/span&gt; &lt;span class="na"&gt;aggregator=&lt;/span&gt;&lt;span class="s"&gt;"sum"&lt;/span&gt; &lt;span class="na"&gt;formatString=&lt;/span&gt;&lt;span class="s"&gt;"#,###"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Cube&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Schema&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to give rights to this file to the user under which Tomcat server is running. In the following command change the user &lt;code&gt;tomcat:tomcat&lt;/code&gt; name to the name under which your Tomcat server works and run it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-RH&lt;/span&gt; tomcat:tomcat &lt;span class="nv"&gt;$TOMCATDIR&lt;/span&gt;/webapps/emondrian/WEB-INF/schema/OnTime.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will edit the Mondrian datasource configuration file. Run following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano &lt;span class="nv"&gt;$TOMCATDIR&lt;/span&gt;/webapps/emondrian/WEB-INF/datasources.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;DataSources&lt;/code&gt; tag with following xml.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;DataSources&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;DataSource&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;DataSourceName&amp;gt;&lt;/span&gt;OnTime&lt;span class="nt"&gt;&amp;lt;/DataSourceName&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;DataSourceDescription&amp;gt;&lt;/span&gt;ClickHouse Sample Data&lt;span class="nt"&gt;&amp;lt;/DataSourceDescription&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;URL&amp;gt;&lt;/span&gt;http://localhost:8080/emondrian/xmla&lt;span class="nt"&gt;&amp;lt;/URL&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;DataSourceInfo&amp;gt;&lt;/span&gt;Provider=mondrian;Jdbc=jdbc:clickhouse://192.168.100.8:8123/datasets;JdbcDrivers=ru.yandex.clickhouse.ClickHouseDriver&lt;span class="nt"&gt;&amp;lt;/DataSourceInfo&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ProviderName&amp;gt;&lt;/span&gt;Mondrian&lt;span class="nt"&gt;&amp;lt;/ProviderName&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ProviderType&amp;gt;&lt;/span&gt;MDP&lt;span class="nt"&gt;&amp;lt;/ProviderType&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;AuthenticationMode&amp;gt;&lt;/span&gt;Unauthenticated&lt;span class="nt"&gt;&amp;lt;/AuthenticationMode&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Catalogs&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Catalog&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"OnTime"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Definition&amp;gt;&lt;/span&gt;/WEB-INF/schema/OnTime.xml&lt;span class="nt"&gt;&amp;lt;/Definition&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Catalog&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Catalogs&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/DataSource&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/DataSources&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit connection string to your ClickHouse dataset in &lt;code&gt;DataSourceInfo&lt;/code&gt; tag using following syntax:&lt;br&gt;
&lt;code&gt;jdbc:clickhouse://&amp;lt;host&amp;gt;:&amp;lt;port&amp;gt;[/&amp;lt;database&amp;gt;][?user=&amp;lt;my_user&amp;gt;&amp;amp;password=&amp;lt;my_password&amp;gt;]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Save (&lt;em&gt;Ctrl-S&lt;/em&gt;) and close (&lt;em&gt;Ctrl-X&lt;/em&gt;) datasources file.&lt;br&gt;
Restart tomcat server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart tomcat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new connection to Mondrian server in Excel to see cubes from your new schema. Select one to browse its data in PivotTable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F62js75ef8igded12k3u6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F62js75ef8igded12k3u6.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try and create your one Mondrian schema for ClickHouse datasets (&lt;a href="https://sergeisemenkov.github.io/eMondrian/docs/Introduction" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If you have any questions or suggestions, feel free to contact me at &lt;a href="mailto:siarhei.semiankou@gmail.com"&gt;siarhei.semiankou@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>clickhouse</category>
      <category>mondrian</category>
      <category>opensource</category>
      <category>excel</category>
    </item>
  </channel>
</rss>
