<rss version="2.0">
  <channel>
    <title>Data &amp; AI</title>
    <link>https://radekrezac.dotnest.net/</link>
    <description><![CDATA[Articles related to Data Management and AI]]></description>
    <item>
      <title>Deploying Azure resource with VS Code</title>
      <link>https://radekrezac.dotnest.net/data-ai/deploying-azure-resource-with-vs-code</link>
      <description><![CDATA[<h2>Prerequsities</h2>
<ul>
<li><a href="https://code.visualstudio.com/download">Install VS Code</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep">Install VS Code Bicep extension</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-node-azure-pack">Install VS Code Azure Tools extension</a></li>
</ul>
<h2>Typical Bicep script sections</h2>
<ul>
<li><strong>Parameters</strong> – values passed in at deployment time</li>
<li><strong>Variables</strong> – calculated or reused values</li>
<li><strong>Resources</strong> – Azure resources being deployed</li>
<li><strong>Modules</strong> (optional) – reusable Bicep components</li>
<li><strong>Outputs</strong> – values returned after deployment</li>
</ul>
<h2>Create Bicep script from existing resources</h2>
<h2>Deployment</h2>
<ol>
<li><a href="">Deploy Bicep files with the Azure CLI</a></li>
</ol>
<pre><code>az deployment group create 
--name ExampleDeployment 
--resource-group ExampleGroup 
--template-file &lt;path-to-bicep&gt; 
--parameters storageAccountType=Standard_GRS
</code></pre>
<ol start="2">
<li><a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/deploy-vscode">Deployment via VS Code</a></li>
<li>Deployment via Devops CD pipeline</li>
</ol>
<h2>Visualization</h2>
]]></description>
      <pubDate>Thu, 08 Jan 2026 08:07:38 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/data-ai/deploying-azure-resource-with-vs-code</guid>
    </item>
    <item>
      <title>Power BI DAX Masterclass</title>
      <link>https://radekrezac.dotnest.net/pbi-masterclass</link>
      <description><![CDATA[<h2>Calculated column vs Mesure</h2>
<p>In Power BI, measures and calculated columns serve distinct purposes:</p>
<h3>Calculated Columns:</h3>
<ul>
<li>A calculated column creates a new physical column in your data table.</li>
<li>It calculates values row by row based on a formula. Hence, it physically exists in your table.</li>
<li>Use calculated columns when you need persistent data that doesn’t depend on report context. For example, these can be useful for data transformations or manipulations.</li>
</ul>
<h3>Measures:</h3>
<ul>
<li>A measure, on the other hand, does not physically exist in the table. It is calculated dynamically when needed, typically when you visualize data in reports.</li>
<li>Measures are evaluated in the context of the filters and slicers applied in your reports, allowing for more flexible and complex calculations.</li>
<li>They are highly reusable across different visuals and reports, which makes them beneficial for calculations such as totals, averages, and variances.</li>
</ul>
<h3>Key Differences:</h3>
<ul>
<li>Calculated columns operate at the row level and are static until refreshed, while measures are dynamic and depend on the visual filtering context.</li>
<li>The performance can be affected by calculated columns especially when they involve complex calculations and cover large datasets.</li>
</ul>
<p>Choosing between them depends on your specific needs for data analysis and visualization. Generally, measures are preferred for their flexibility and dynamic nature.</p>
<h2>Date Tables</h2>
<p>In Power BI, both the <code>CALENDARAUTO</code> and <code>CALENDAR</code> functions are used to create date tables, but they differ in their approach and flexibility:</p>
<h3>CALENDARAUTO:</h3>
<ul>
<li>Automatically generates a date table based on the existing date values in your model.</li>
<li>It finds the earliest and latest dates in your data to create a contiguous range of dates without any missing dates.</li>
<li>You don’t need to specify start or end dates, making it quicker to implement. However, it does not allow for customization of the start date or fiscal year considerations.</li>
</ul>
<h3>CALENDAR:</h3>
<ul>
<li>Requires you to manually specify the start and end dates for the date table.</li>
<li>This provides more flexibility as you can set exact dates and adjust for fiscal years.</li>
<li>For example, you might call it with <code>CALENDAR(DATE(2020, 1, 1), DATE(2025, 12, 31))</code> to define the exact range you desire.</li>
</ul>
<h3>Key Considerations:</h3>
<ul>
<li>If you want an automatic date range based on your existing data without manual input, use CALENDARAUTO.</li>
<li>If you need precise control over the date range and fiscal settings, opt for CALENDAR.</li>
</ul>
<h3>Date Table Script</h3>
<ul>
<li>In our case script is based on existing table <code>sales</code> and column <code>date</code></li>
</ul>
<pre><code class="language-sql">DateTable = 
ADDCOLUMNS ( 
CALENDAR(MINX('sales','sales'[date]),MAXX('sales','sales'[date])),
"DateAsInteger", FORMAT ( [date], "YYYYMMDD" ),
 "Year", YEAR ( [date] ), "MonthNo", FORMAT ( [date], "MM" ), 
"YearMonthNo", FORMAT ( [date], "YYYY/MM" ), 
"YearMonth", FORMAT ( [date], "YYYY/mmm" ), 
"MonthShort", FORMAT ( [date], "mmm" ),
"MonthLong", FORMAT ( [date], "mmmm" ), 
"WeekNo", WEEKDAY ( [date] ), 
"WeekDay", FORMAT ( [date], "dddd" ), 
"WeekDayShort", FORMAT ( [date], "ddd" ), 
"Quarter", "Q" &amp; FORMAT ( [date], "Q" ), 
"YearQuarter", FORMAT ( [date], "YYYY" ) &amp; "/Q" &amp; FORMAT ( [date], "Q" ))
</code></pre>
<h2>Key Measures table</h2>
<h3>Purpose:</h3>
<p>A Key Measures table consolidates <em><strong>all your measures in one place</strong></em>, making them easier to manage and reference across your reports. This organization helps improve readability and access to all key calculations.</p>
<h3>Creating the Table:</h3>
<ul>
<li>Go to the home ribbon in Power BI.</li>
<li>Click on "Enter Data" to create a new table.</li>
<li>You don’t need to input any data; simply name the table “Key Measures Table”.</li>
<li>Click "Load" to create the empty table.</li>
</ul>
<h3>Moving Measures:</h3>
<ul>
<li>Once your Key Measures table is created, you can start moving existing measures into this new table for better organization.</li>
<li>Select the measure you wish to relocate and change its destination to the Key Measures table.
<img class="w-100" src="/media/DM/measure-table.jpg"></li>
</ul>
<h3>Benefits:</h3>
<p>By organizing your measures into a Key Measures table, you can not only make your data model cleaner but also leverage the full benefits of measure reusability across different visuals and reports. This organization aids in quicker access and clearer insights during your analysis.</p>
<h2>COUNT Agregation functions</h2>
<p>In Power BI, the DAX functions <code>COUNT</code>, <code>COUNTA</code>, <code>COUNTBLANK</code>, <code>DISTINCTCOUNT</code>, and <code>COUNTROWS</code> are important for tallying data based on different criteria:</p>
<h3>COUNT:</h3>
<p>Counts the number of rows that contain numeric data in a specified column.
Use it when you specifically want to count only the rows that contain numbers.</p>
<h3>COUNTA:</h3>
<p>Counts the number of rows that are not empty in a specified column, regardless of the data type (numeric or text).
Use this function when you want to count all non-blank entries.</p>
<h3>COUNTBLANK:</h3>
<p>Counts the number of blank rows in a specified column.
This is useful to determine how many entries are missing data.</p>
<h3>DISTINCTCOUNT:</h3>
<p>Counts the number of unique values in a specified column, excluding duplicates.
Use it when you want to analyze how many distinct entries exist in that column.</p>
<h3>COUNTROWS:</h3>
<p>Counts the number of rows in a table or a table expression.
This function is helpful when you want to know the total number of rows available in a specific data table.</p>
<h3>Summary:</h3>
<ul>
<li>Use <strong>COUNT</strong> for numeric-only count.</li>
<li>Use <strong>COUNTA</strong> for overall non-empty count.</li>
<li>Use <strong>COUNTBLANK</strong> for counting missing data.</li>
<li>Use <strong>DISTINCTCOUNT</strong> for counting unique values.</li>
<li>Use <strong>COUNTROWS</strong> for total row count in a table.</li>
</ul>
<h2>X functions</h2>
<p>In Power BI, the X functions (often referred to as <strong>iterator functions</strong>) are a powerful category of DAX functions that allow you to perform operations on rows of a table, returning a result based on each individual row's context. Here are a few key examples:</p>
<h3>SUMX:</h3>
<p>Iterates through a table, evaluating an expression for each row and returning the sum of those values.
Use it when you want to create a cumulative total based on a calculated or derived column.</p>
<h3>AVERAGEX:</h3>
<p>Similar to SUMX, but instead, it computes the average of the values returned by the expression for each row in the table.</p>
<h3>MINX and MAXX:</h3>
<p>These functions return the smallest or largest value, respectively, from a set of values returned by an expression evaluated for each row.</p>
<p>###COUNTX:
Counts the number of rows that contain non-blank results from the expression evaluated for each row in the table.</p>
<h3>MEDIANX:</h3>
<p>Returns the median of a set of values specified by evaluating an expression for each row in the table.</p>
<h3>General Use Cases:</h3>
<p>The X functions are especially useful for calculations that depend on row context, enabling you to iterate through tables and apply complex logic that standard aggregation functions (like SUM or AVERAGE) cannot handle by themselves.</p>
<h3>Key Advantages:</h3>
<p>By using iterator functions, you can create more dynamic and context-aware calculations, which can lead to deeper insights in your Power BI reports.</p>
<p>Using X functions can greatly enhance your DAX formulas, providing versatility and power in your data analysis. Understanding how to effectively apply these functions will significantly improve your capability to create sophisticated reports and dashboards in Power BI.</p>
<h2>Power BI vs Excel</h2>
<p>Power BI and Excel are both powerful tools for data analysis, but they serve different purposes and have distinct functionalities.</p>
<h3>Data Structure:</h3>
<ul>
<li>In Excel, calculations are centered around individual cells. You reference these cells directly to perform calculations. For instance, if you want to calculate revenue, you multiply values from specific cells.</li>
<li>In contrast, Power BI operates on a model where the focus is on tables and columns rather than individual cells. The data is structured in tables with relationships between them, allowing for more complex data analysis.</li>
</ul>
<h3>Analysis Capabilities:</h3>
<ul>
<li>Excel is great for quick calculations and straightforward data manipulation, making it ideal for smaller datasets or less complex analyses.</li>
<li>Power BI excels in handling larger datasets and provides advanced analytical capabilities. It employs DAX (Data Analysis Expressions) for creating measures and calculated columns, enabling users to perform sophisticated data modeling and insights generation.</li>
</ul>
<h3>Visualization:</h3>
<ul>
<li>While Excel offers chart and graph capabilities, Power BI provides richer visualizations with dynamic features. It allows users to create intricate dashboards that can interact with the data in real-time.</li>
</ul>
<h3>Collaboration and Sharing:</h3>
<ul>
<li>Power BI offers enhanced features for collaboration and sharing reports online, making it better suited for team environments and organizational use.</li>
</ul>
<p>Overall, if you need detailed visualizations and work with large datasets, Power BI is typically the better choice. For simpler tasks or if you are already experienced in using Excel, it may suffice for your needs.</p>
<h2>Filter vs Row context</h2>
<p>In Power BI, understanding the difference between filter context and row context is crucial for effectively using DAX (Data Analysis Expressions).</p>
<h3>Filter Context</h3>
<ol>
<li><strong>Definition</strong>: Filter context refers to the set of filters applied to the data before performing calculations. It determines which rows of data are included in the calculation.</li>
<li><strong>Usage</strong>: An example of using filter context is through the CALCULATE function. For instance, you might use CALCULATE to compute total sales for a specific category:</li>
</ol>
<ul>
<li><strong>Code</strong>:
<code>TotalSalesElectronics = CALCULATE(SUM(Sales[SalesAmount]), FILTER(Sales, Sales[ProductCategory] = "Electronics"))</code>
Here, FILTER creates a new table containing only the rows where the product category is "Electronics," thereby modifying the filter context for the SUM function.</li>
</ul>
<h3>Row Context</h3>
<ol>
<li><strong>Definition</strong>: Row context exists when a calculation is performed on a per-row basis. This means that for each row in a table, certain expressions are evaluated before any aggregation occurs.</li>
<li><strong>Usage</strong>: You often encounter row context when using functions like SUMX or AVERAGEX. For example, with SUMX, it calculates an expression for each row (like quantity times price) and then aggregates those results:</li>
</ol>
<ul>
<li><strong>Code</strong>:
<code>TotalRevenue = SUMX(Sales, Sales[Quantity] * Sales[Price])</code>
In this case, the expression is calculated for each row before summing the results.</li>
</ul>
<h3>Key Differentiations</h3>
<ul>
<li><strong>Context Transition</strong>: When you use a function like CALCULATE, it converts a row context into a filter context, allowing you to change how filters are applied to the data.</li>
<li><strong>Memory Usage</strong>: Row context calculations might require more memory, as each computed result is stored before aggregation.</li>
</ul>
<p>Understanding these contexts will help you to build more effective DAX measures in Power BI, ultimately enhancing your data analysis capabilities.</p>
<h2>CALCULATE function</h2>
<p>The <code>CALCULATE</code> function in DAX is a powerful tool <strong>used to change the context</strong> in which a calculation is performed in Power BI.
Here’s a breakdown of how the CALCULATE function works:</p>
<h3>Purpose</h3>
<p>CALCULATE modifies the filter context before performing calculations, allowing for nuanced data analysis based on specified criteria.</p>
<h3>Syntax</h3>
<p>The basic syntax of the CALCULATE function is:</p>
<pre><code>CALCULATE(&lt;expression&gt;, &lt;filter1&gt;, &lt;filter2&gt;, ...)
</code></pre>
<ul>
<li><code>&lt;expression&gt;</code>: This is the calculation you want to evaluate (e.g., <code>SUM</code>, <code>AVERAGE</code>, etc.).</li>
<li><code>&lt;filter1&gt;, &lt;filter2&gt;, ...</code>: These are the filters that modify the context of the calculation.</li>
</ul>
<h3>Example</h3>
<p>For instance, if you want to calculate total sales for a specific category, the formula would look something like this:</p>
<pre><code>TotalSalesElectronics = CALCULATE(SUM(Sales[SalesAmount]), FILTER(Sales, Sales[ProductCategory] = "Electronics"))
</code></pre>
<p>In this example:</p>
<ul>
<li><code>SUM(Sales[SalesAmount])</code> is the expression that computes total sales.</li>
<li><code>FILTER(Sales, Sales[ProductCategory] = "Electronics")</code> modifies the filter context so that only sales data for the "Electronics" category is considered.</li>
</ul>
<h3>Key Points</h3>
<ul>
<li>CALCULATE can be used to apply multiple filters, making it flexible for various scenarios.</li>
<li>It’s essential for creating dynamic measures that can adapt to different user selections and slicers in your reports.</li>
</ul>
<h3>Importance</h3>
<p>Understanding how to effectively use CALCULATE is crucial for building robust, context-aware measures in Power BI that can provide deeper insights into your data.</p>
<h2>FILTER function</h2>
<p>The <code>FILTER</code> function in DAX is a powerful tool for creating custom filters on tables. Could be used as FILTER part of the <code>CALCULATE</code> function:</p>
<h3>Purpose</h3>
<p>The FILTER function is primarily used to <strong>return a table that includes only the rows that meet specific criteria</strong>. It operates in a way that lets you specify the filtering conditions dynamically within your DAX formulas.</p>
<h3>Syntax</h3>
<p>The basic syntax of the FILTER function is:</p>
<pre><code>FILTER(&lt;table&gt;, &lt;filter_expression&gt;)
</code></pre>
<ul>
<li><code>&lt;table&gt;</code>: The table you want to filter.</li>
<li><code>&lt;filter_expression&gt;</code>: An expression that defines the conditions that must be met for rows to be included in the returned table.</li>
</ul>
<h3>Example</h3>
<p>Suppose you have a Products table and want to create a new table that includes only products with a price greater than $5. You would use the FILTER function as follows:</p>
<pre><code>FilteredProducts = FILTER(Products, Products[Price] &gt; 5)
</code></pre>
<p>In this case, <code>FilteredProducts</code> will contain only those rows from the <code>Products</code> table where the price exceeds $5.</p>
<h3>Key Points</h3>
<ul>
<li><strong>Table Function</strong>: FILTER is considered a table function because it returns a table as a result. This is distinct from scalar functions, which return a single value.</li>
<li><strong>Used in CALCULATE</strong>: Often, the FILTER function is used within the CALCULATE function to modify the evaluation context of a measure. This allows you to perform calculations based on a specific subset of data.</li>
</ul>
<h3>Considerations</h3>
<ul>
<li>Using FILTER effectively can lead to more sophisticated data analysis, allowing for greater insights by dynamically adjusting the data subsets being analyzed.</li>
<li>It’s crucial to understand how it interacts with row and filter context to leverage its full potential.</li>
</ul>
<h2>ALL function</h2>
<p>The <code>ALL</code> function in DAX is used to remove filters from a specified table or column. This can be particularly useful when you want to perform calculations that require analyzing the complete dataset without any applied filters.</p>
<h3>Purpose</h3>
<p>The ALL function allows you to <strong>ignore any filters</strong> in your context, returning the entire table or column, and is often <strong>used in conjunction with</strong> functions like <code>CALCULATE</code> to create metrics that require a different evaluation context.</p>
<h3>Syntax</h3>
<p>The syntax for the ALL function is:</p>
<pre><code>ALL(&lt;table_name_or_column_name&gt;)
</code></pre>
<ul>
<li><code>&lt;table_name_or_column_name&gt;</code>: This specifies the table or column from which you want to remove filters.</li>
</ul>
<h3>Example</h3>
<ol>
<li>For instance, if you want to calculate the total sales regardless of any filters applied in your report visuals, you could write:</li>
</ol>
<pre><code>TotalSalesAll = CALCULATE(SUM(Sales[SalesAmount]), ALL(Sales))
</code></pre>
<p>In this example:</p>
<ul>
<li><code>SUM(Sales[SalesAmount])</code> calculates the total sales amount.</li>
<li><code>ALL(Sales)</code> removes any filters applied to the Sales table, ensuring that the total sales calculation considers all rows in the table.</li>
</ul>
<ol start="2">
<li>if you want to calculate percentage of the revenue by state filter applied in your report visuals, you could write:</li>
</ol>
<pre><code>Revenue filtered by a state = Revenur Mesure / CALCULATE((Revenue Measure), ALL(location[state]))
</code></pre>
<p>In this example:</p>
<ul>
<li><code>Revenur Mesure</code> revenue for each column calcilated by SUMX.</li>
<li><code>ALL(location[state])</code> removes any filters applied to the <code>state</code> of the <code>location</code> table, ensuring that the total revenue calculation considers all rows in the table.</li>
</ul>
<h3>Key Points</h3>
<p>The ALL function is beneficial for creating calculated measures that need overall insights, such as calculating percentages of total sales or comparing values against grand totals.
Different variations of <code>ALL</code> exist, including <code>ALLSELECTED</code>, which removes filters but keeps the filters applied by the user’s selections in slicers or visuals.
Using the ALL function allows for a more profound and comprehensive analysis across your data.</p>
<h2>ALLSELECTED function</h2>
<p>The <code>ALLSELECTED</code> function in DAX is used to <strong>remove filters from columns or tables while still considering any filters applied in the current report context</strong>, such as <strong>slicers</strong>, without disregarding selections made by the user.</p>
<h3>Purpose</h3>
<p>It enables you to compute values over a specified range of data, which may involve filters from the visual elements of the report but not those defined in the measure itself.</p>
<h3>Syntax</h3>
<p>The syntax for ALLSELECTED is:</p>
<pre><code>ALLSELECTED(&lt;table_name_or_column_name&gt;)
</code></pre>
<ul>
<li><code>&lt;table_name_or_column_name&gt;</code>: This is the specific table or column for which you want to retain the filters from the user’s selections while removing others.</li>
</ul>
<h3>Example</h3>
<p>Suppose you want to calculate the percentage of sales compared to total sales considering only the filters from slicers. You could use:</p>
<pre><code>SalesPercentage = DIVIDE(SUM(Sales[SalesAmount]), CALCULATE(SUM(Sales[SalesAmount]), ALLSELECTED(Sales)))
</code></pre>
<p>In this formula:</p>
<ul>
<li><code>SUM(Sales[SalesAmount])</code> calculates the sales for the current context.</li>
<li><code>ALLSELECTED(Sales)</code> removes any filters on the <code>Sales</code> table but respects filters from slicers, ensuring that the calculation reflects the intended scope.</li>
</ul>
<h3>Key Points</h3>
<p><code>ALLSELECTED</code> is particularly useful for creating responsive measures in reports where user interaction (like slicers or filters) needs to modify results dynamically while still allowing a full range of data to be analyzed.
It provides flexibility when crafting insights that depend on user-driven contexts, such as dashboards where users might want to see insights filtered by certain criteria while still maintaining a broader view of the data.</p>
<h2>ALLEXCEPT function</h2>
<p>The <code>ALLEXCEPT</code> function in DAX is used to <strong>remove filters from all columns in a table except for the specified columns</strong>. This function is particularly useful when you want to maintain certain filters while disregarding others during calculations.</p>
<h3>Purpose</h3>
<p>The <code>ALLEXCEPT</code> function is ideal when you want to summarize data while keeping specific dimensions in the filter context, allowing for more targeted analysis.</p>
<h3>Syntax</h3>
<p>The syntax for ALLEXCEPT is:</p>
<pre><code>ALLEXCEPT(&lt;table&gt;, &lt;column_1&gt;, &lt;column_2&gt;, ...)
</code></pre>
<ul>
<li><code>&lt;table&gt;</code>: The table from which to remove all filters.</li>
<li><code>&lt;column_1&gt;, &lt;column_2&gt;, ...</code>: The columns that you want to keep the filters for.</li>
</ul>
<h3>Example</h3>
<p>For instance, if you have a <code>Sales</code> table and want to calculate the total sales while keeping the filter for <code>Region</code>, you might write the following:</p>
<pre><code>TotalSalesByRegion = CALCULATE(SUM(Sales[SalesAmount]), ALLEXCEPT(Sales, Sales[Region]))
</code></pre>
<p>In this example:</p>
<ul>
<li><code>SUM(Sales[SalesAmount])</code> computes the total sales.</li>
<li><code>ALLEXCEPT(Sales, Sales[Region])</code> allows the <code>Region</code> filters to remain while ignoring other filters in the Sales table.</li>
</ul>
<p>###Key Points
<code>ALLEXCEPT</code> is useful for creating measures that need to respect specific dimensions while performing calculations over the entire dataset.
It helps in scenarios where you want to create comparisons (e.g., percentage calculations) that focus on certain filter aspects without losing other important insights from your data.</p>
<h2>Logical Operators</h2>
<p>In DAX, logical operators allow you to create <strong>complex filtering conditions</strong> in your calculations. Here are the primary logical operators used in DAX:</p>
<ol>
<li><strong>AND</strong> Operator (<code>&amp;&amp;</code>)
The AND operator is used to combine multiple conditions, where all conditions must be true for the entire expression to evaluate to true.
Example:</li>
</ol>
<pre><code>IF(Sales[Amount] &gt; 1000 &amp;&amp; Sales[Region] = "North", "High Sale", "Low Sale")
</code></pre>
<ol start="2">
<li><strong>OR</strong> Operator (<code>||</code>)
The OR operator allows for conditions where at least one of the conditions must be true for the expression to evaluate to true.
Example:</li>
</ol>
<pre><code>IF(Sales[Amount] &lt; 500 || Sales[Region] = "South", "Low Sale or in South", "Regular Sale")
</code></pre>
<ol start="3">
<li><strong>NOT</strong> Operator (<code>NOT</code>)
The NOT operator is used to negate a condition. If the condition is true, NOT makes it false and vice versa.
Example:</li>
</ol>
<pre><code>IF(NOT(Sales[Region] = "East"), "Not in East", "In East")
</code></pre>
<ol start="4">
<li>Combining Conditions
You can combine these logical operators to create more complex conditions. However, be mindful of the order of operations; the AND operator is evaluated before the OR operator.
Example:</li>
</ol>
<pre><code>IF((Sales[Amount] &gt; 1000 &amp;&amp; Sales[Region] = "North") || (Sales[Amount] &lt; 500), "Specific Sale Condition", "Other")
</code></pre>
<h3>Usage in Filtering</h3>
<p>These operators are often used with functions like <code>CALCULATE</code> to create dynamic measures based on complex filtering criteria. For example, you could filter a dataset to include products that are either above a certain price point or within a specific category, as mentioned in the course where the operator logic was discussed.</p>
<p>Understanding how to effectively use logical operators can help you build sophisticated analytics in your DAX queries.</p>
<h2>VALUES and AVERAGEX function</h2>
<p>The VALUES function and the AVERAGEX function in DAX serve distinct purposes but can work together effectively in your calculations.</p>
<h3>VALUES Function</h3>
<p>The <code>VALUES</code> function returns a one-column table that contains the distinct values from the specified column or table. It can be used to create a unique list of values for further calculations.
<strong>Example Use</strong>: If you want to get a list of unique values from a date column, you would use:</p>
<pre><code>VALUES(DateTable[Date])
</code></pre>
<h3>AVERAGEX Function</h3>
<p>The <code>AVERAGEX</code> function iterates through a table, evaluating an expression and returning the average of those values. It is an iterator function, meaning it processes each row of the table specified.
<strong>Syntax</strong>:</p>
<pre><code>AVERAGEX(&lt;table&gt;, &lt;expression&gt;)
</code></pre>
<p><strong>Example Use</strong>: To calculate the average sales amount by iterating over a table of sales data:</p>
<pre><code>AVERAGEX(SalesTable, SalesTable[SalesAmount])
</code></pre>
<h3>Combining VALUES and AVERAGEX</h3>
<p>You can combine these two functions to calculate averages based on distinct values. For example, to calculate the monthly average revenue, you could write:</p>
<pre><code>MonthlyAverageRevenue = AVERAGEX(VALUES(DateTable[YearMonth]), [RevenueMeasure])
</code></pre>
<p>In this case:
<code>VALUES(DateTable[YearMonth])</code> provides a unique list of year-month combinations, and for each combination, the <code>[RevenueMeasure]</code> is evaluated and averaged.
This combination allows for powerful analytics where averages are calculated based on distinct segments of your data, providing insights tailored to your reporting needs.</p>
<h2>RANKX function</h2>
<p>The <code>RANKX</code> function in DAX is used to rank values within a specified context. It allows you to determine the rank of an expression evaluated for each row across a table. This is particularly useful for identifying top-performing items based on a certain measure, such as revenue.</p>
<h3>Purpose</h3>
<p>The RANKX function assigns a rank (1 for the highest value, 2 for the next highest, etc.) to each row in a specified table based on the evaluation of an expression.</p>
<h3>Syntax</h3>
<p>The syntax for RANKX is:</p>
<pre><code>RANKX(&lt;table&gt;, &lt;expression&gt;, [&lt;value&gt;, &lt;order&gt;])
</code></pre>
<ul>
<li><code>&lt;table&gt;</code>: The table containing the values to rank.</li>
<li><code>&lt;expression&gt;</code>: The expression to evaluate and rank.</li>
<li><code>&lt;value&gt;</code> (optional): An optional value that you can provide when the expression returns a blank.</li>
<li><code>&lt;order&gt;</code> (optional): Sort order (0 for descending, 1 for ascending; defaults to descending).</li>
</ul>
<h3>Example</h3>
<p>For example, if you want to rank customers based on their quarterly average revenue, you might create a measure like this:</p>
<pre><code>Ranking by Quarterly Average = CALCULATE( RANKX ( ALLSELECTED( customer ) , [Quarterly Average Revenue] ) ,
ALL ( DateTable[Year] ) )
</code></pre>
<p><img class="w-100" src="/media/DM/ranx.jpg"></p>
<p>In this example:</p>
<ul>
<li><code>ALLSELECTED( customer )</code> is the table we are ranking with <code>customer</code> slicer applied.</li>
<li><code>[QuarterlyAverageRevenue]</code> is the measure for which ranks are calculated.</li>
<li><code>ALL ( DateTable[Year] )</code> - remove all filters based on <code>Year</code> of the <code>DateTable</code> table</li>
</ul>
<h3>Practical Use</h3>
<ul>
<li>You can use RANKX in tandem with other measures to filter the top performers or analyze performance over time. For instance, to filter and see only the top ten customers ranked by quarterly average revenue, you could create a calculated table or fit this measure in a visual filter.</li>
<li>Combining RANKX with a helper table, such as a Top N filter, can also improve your analysis by giving you dynamic control over how many top-ranked items to display.</li>
</ul>
<h2>IF function &amp; Top-N filter</h2>
<p>The <code>IF</code> function in DAX can be effectively used in conjunction with a Top-N filter to dynamically filter data based on ranking. Here's how you can implement a Top-N filter using an IF statement.</p>
<h3>Creating a Top-N Filter</h3>
<ol>
<li><strong>Helper Table</strong>: First, create a helper table that specifies your Top-N options such as Top 3, Top 5, Top 10, etc. This table will allow you to control how many entries you want to see in your report.</li>
</ol>
<p><img class="w-30" src="/media/DM/topn-table.jpg"></p>
<ol start="2">
<li><strong>Creating the Measure</strong>: You will then need to create a measure that utilizes the ranking and implements the IF statement to determine whether to include a particular value based on its rank.</li>
<li><strong>Sample Measure</strong>: Here’s an example of how you might create a measure that filters to only show revenue for the top N ranked customers:</li>
</ol>
<pre><code>TopN Revenue = IF ( [Ranking by Quarterly Average] &lt;= MAX(TopNFilter[TopNValue]) , 
	[Revenue Measure] , 
	BLANK() ) 
</code></pre>
<p><img class="w-100" src="/media/DM/topn-revenue.jpg"></p>
<p>In this example, <code>[Ranking by Quarterly Average]</code> is the measure that calculates the rank, and <code>[RevenueMeasure]</code> calculates the revenue. The IF statement checks if the rank is within the specified Top-N value.</p>
<h3>How It Works</h3>
<ul>
<li>The measure calculates the ranking for each customer and then checks if it falls within the defined Top-N range. If true, it returns the corresponding revenue; if false, it returns a blank.</li>
<li>This allows for flexible reporting and analysis where you can easily adjust the Top-N filter to view different segments of your data.</li>
</ul>
<h3>Practical Application</h3>
<p>Using this approach, you can dynamically analyze which customers, products, or any entities perform within the top range based on your chosen criteria, enhancing your insights into business performance.</p>
<h2>Variables</h2>
<p>In DAX, variables are a powerful feature that allows you to store values and expressions for later use within a formula. This enhances the readability and maintainability of your DAX code, and can also improve performance by avoiding repeated calculations.</p>
<h3>Creating Variables</h3>
<p>You can define variables in a DAX formula using the <code>VAR</code> keyword followed by an assignment, and then use these variables in the subsequent calculations. The structure is as follows:</p>
<pre><code>MeasureName = 
VAR VariableName = Expression
RETURN
    AnotherExpressionUsing(VariableName)
</code></pre>
<h3>Example</h3>
<p>Here's a practical example of using a variable in a measure designed to calculate total sales while excluding a specific product category:</p>
<pre><code>TotalSalesExcludingCategory = 
VAR TotalSales = SUM(Sales[SalesAmount])
VAR ExcludedSales = CALCULATE(SUM(Sales[SalesAmount]), Sales[Category] = "ExcludedCategory")
RETURN
    TotalSales - ExcludedSales
</code></pre>
<p>In this example:</p>
<ul>
<li><code>TotalSales</code>  holds the total sales amount.</li>
<li><code>ExcludedSales</code> calculates sales for a category that needs to be excluded.</li>
<li>The measure <strong>subtracts</strong> <code>ExcludedSales</code> from <code>TotalSales</code> and returns the result.</li>
</ul>
<h3>Benefits of Using Variables</h3>
<ul>
<li><strong>Improved Readability</strong>: Using variables makes your DAX formulas easier to understand.</li>
<li><strong>Performance</strong>: Instead of calculating the same expression multiple times, you calculate it once and reference it through the variable.</li>
<li><strong>Complex Calculations</strong>: Helps in breaking down complex calculations into simpler parts, making debugging easier.</li>
</ul>
<h2>Time Intelligence &amp; DATEADD</h2>
<p>The <code>DATEADD</code> function in DAX is a powerful Time Intelligence function used for <strong>shifting dates by a specified number of intervals</strong>, which can be days, months, quarters, or years. This function <strong>allows you to create calculations that compare data from different time periods</strong>, making it essential for time-based analysis.</p>
<h3>Syntax</h3>
<p>The syntax for DATEADD is:</p>
<pre><code>DATEADD(&lt;dates&gt;, &lt;number&gt;, &lt;time_unit&gt;)
&lt;dates&gt;: A column that contains dates.
&lt;number&gt;: The number of intervals to add (can be negative for subtraction).
&lt;time_unit&gt;: The interval to use (e.g., DAY, MONTH, QUARTER, YEAR).
</code></pre>
<h3>Example</h3>
<p>For instance, if you have a measure that calculates revenue, and you want to see the revenue from two days ago, you can use DATEADD like this:</p>
<pre><code>RevenueTwoDaysAgo = 
CALCULATE(
    [RevenueMeasure],
    DATEADD(DateTable[Date], -2, DAY)
)
</code></pre>
<p>In this example:</p>
<ul>
<li><code>[RevenueMeasure]</code> is the measure you're calculating.
-<code>DateTable[Date]</code> is the date column, and -2 specifies to go back two days.</li>
</ul>
<h3>Use Case</h3>
<p>The <code>DATEADD</code> function is particularly useful when you want to create reports that compare current metrics with those from previous periods. By shifting the context of your calculations, you can easily compute growth rates, year-over-year changes, and other time-based insights.</p>
]]></description>
      <pubDate>Thu, 18 Dec 2025 17:48:56 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/pbi-masterclass</guid>
    </item>
    <item>
      <title>Data Catalog 3.0</title>
      <link>https://radekrezac.dotnest.net/data-catalog-3</link>
      <description><![CDATA[<h2>Role of the Data Catalog in Data Mesh</h2>
<p>A <strong>Data Mesh</strong> is a <em><strong>decentralized architectural paradigm</strong></em>, while a <strong>Data Catalog</strong> is a <em><strong>tool or component used within</strong></em> it. A Data Mesh focuses on organizational principles like <em><strong>domain ownership</strong></em> and treating <em><strong>data as a product</strong></em>, whereas a Data Catalog provides a way to <em><strong>discover and inventory all the data assets</strong></em>, including these data products, across the decentralized domains. Essentially, data catalogs are foundational and necessary for a data mesh to function effectively by providing a central point of access and discovery for decentralized data</p>
<p>Starting around 2016, the modern data stack went mainstream. This refers to a flexible collection of tools and capabilities that help businesses today <strong>store</strong>, <strong>manage</strong>, and <strong>use</strong> their data. These tools are unified by three key ideas:</p>
<ul>
<li>Self-service for a diverse range of users</li>
<li>“Agile” data management</li>
<li>Cloud-first and cloud-native</li>
</ul>
<h3>Key elements and tools in the modern Data Stack</h3>
<p><img class="w-100" src="/media/DM/data-stack.jpg"></p>
]]></description>
      <pubDate>Sun, 07 Dec 2025 19:28:59 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/data-catalog-3</guid>
    </item>
    <item>
      <title>dbt on Databricks</title>
      <link>https://radekrezac.dotnest.net/dbt-databricks</link>
      <description><![CDATA[<h2>dbt Labs</h2>
<p>dbt Labs is the company behind dbt (data build tool), which is an open-source analytics engineering tool. It enables data professionals to transform their raw data into structured datasets that can provide valuable insights through SQL-based transformations. dbt Labs focuses on enhancing data transformation processes by providing a modular, version-controlled framework that facilitates integration with various data platforms like Databricks, Snowflake, and Microsoft Fabric.</p>
<p>The key offerings from dbt Labs include:</p>
<ol>
<li><strong>dbt Core</strong>: The open-source version of dbt that allows users to create their models and manage data transformations.</li>
<li><strong>dbt Cloud</strong>: A hosted version of dbt that offers additional features such as a user interface, collaboration tools, and scheduling capabilities to streamline workflows.</li>
<li><strong>Support and Community</strong>: dbt Labs encourages community contributions and has an active ecosystem where users share knowledge and best practices.</li>
</ol>
<h2>Databricks</h2>
<p>Databricks is a unified data analytics platform that provides a collaborative environment for data engineering, data science, and machine learning. It is built around <em>Apache Spark</em> and integrates with various cloud services, allowing organizations to efficiently process and analyze large amounts of data.</p>
<p>Key features of Databricks include:</p>
<ol>
<li><strong>Lakehouse Architecture</strong>: Combines data lakes and data warehouses into a single architecture, enabling easier data management and analytics.</li>
<li><strong>Collaborative Workspace</strong>: Offers notebooks that support multiple languages (Python, R, Scala, SQL) for data scientists and analysts to collaborate in real-time.</li>
<li><strong>Unified Analytics</strong>: Allows users to perform tasks related to data processing, analytics, and machine learning in a seamless way without needing separate tools.</li>
<li><strong>Integration with Other Tools</strong>: Databricks easily integrates with various external tools and platforms, including <em><strong>dbt</strong></em>, which helps in transforming raw data into structured insights using SQL.</li>
<li><strong>Scalability and Performance</strong>: Provides high-performance capabilities to handle demanding workloads and large datasets, making it suitable for enterprises.</li>
</ol>
<p>Databricks enhances data accessibility and usability, helping organizations leverage their data effectively for decision-making and strategic planning.</p>
<h2>Connect dbt to Databricks</h2>
<p>To connect the Databricks Unity Catalog to your dbt project, follow these steps:</p>
<ol>
<li><p><strong>Installation Prerequisites</strong>: Ensure that you have both dbt and the Databricks adapter installed. You can check the official documentation for installation</p>
</li>
<li><p><strong>Create SQL Warehouse</strong>: Create an SQL warehouse that will be connected to the dbt project using connection details.</p>
<p><img class="w-100" src="/media/DM/sql-warehouse.jpg"></p>
</li>
<li><p><strong>Create a new Unity Catalog</strong>:  New created unity catalog, using created warehouse in the previous step, will be then connected to dbt project.</p>
<p><img class="w-100" src="/media/DM/db-create-catalog.jpg"></p>
</li>
<li><p><strong>Create a new Connection</strong>:  New created unity catalog, using created warehouse in the previous step, will be then connected to dbt project.</p>
<ul>
<li>Go to the Account Settings/Connection tab.</li>
<li>Select <em>Databricks</em></li>
<li>Set the server hostname and HTTP path. Obtain these from your <em>Databricks SQL warehouse connection details</em>.</li>
<li>Optionally set the name of created Unity Catalog</li>
</ul>
<p><img class="w-100" src="/media/DM/dbt-connection.jpg"></p>
<p><img class="w-100" src="/media/DM/dbt-connection-settings.jpg"></p>
</li>
<li><p><strong>Set Up Access Tokens</strong>:</p>
<ul>
<li>Go to the Databricks Settings</li>
<li>Generate a new token under Developer/Access Tokens tab</li>
<li>Copy the token</li>
</ul>
<p><img class="w-100" src="/media/DM/db-token.jpg"></p>
</li>
<li><p><strong>Create and init dbt project:</strong></p>
<ul>
<li>Go to the Account Settings/Projects tab.</li>
<li>Select <em>New project</em></li>
<li>Enter name of the project</li>
<li>Select created Connection</li>
<li>Select <em>Token</em> as Auth meto a paste the copied Databricks token</li>
<li>Leave a schema as it is</li>
<li>Setup a repository (1)</li>
<li>Create a repository (2)</li>
<li>Go to Studio Tab</li>
<li>Init and commit repository to new branch (3)</li>
</ul>
</li>
</ol>
<p><img class="w-100" src="/media/DM/dbt-new-project.jpg"></p>
<p><img class="w-100" src="/media/DM/dbt-create-repo.jpg"></p>
<p>This procedure integrates Databricks Unity Catalog into your dbt project, allowing you to effectively manage and utilize your data assets.</p>
]]></description>
      <pubDate>Sun, 07 Dec 2025 19:03:47 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/dbt-databricks</guid>
    </item>
    <item>
      <title>Power BI Incremental Refresh</title>
      <link>https://radekrezac.dotnest.net/pbi-incremental-refresh</link>
      <description><![CDATA[<p>Incremental refresh is a feature in Power BI that allows you to increase efficiency when <strong>refreshing data by only updating the most recent data instead of completely rewriting the entire dataset</strong>. This is especially useful for large datasets as it minimizes the amount of data handled during the refresh process, reducing load times and resource usage.</p>
<p>Here’s how incremental refresh works:</p>
<ul>
<li><strong>Data Partitioning</strong>: The data is partitioned <em><strong>based on defined time frames,</strong></em> like days or months. This allows Power BI to identify which data partitions need to be refreshed based on changes.</li>
<li><strong>Change Detection</strong>: It can check for changes in specific fields (like the maximum value of a date field) and trigger a refresh only if there’s new data to incorporate. For example, if today's date doesn't have new data since the last refresh, it won't load that day's data again.</li>
<li><strong>Limitations</strong>: Incremental refresh is <em><strong>available only in Power BI service</strong></em>, and usually <em><strong>requires a Power BI Premium license</strong></em> for extensive capabilities. In the Pro version, while you might refresh data multiple times per day, it does not include incremental refresh.</li>
</ul>
<p>This approach helps keep data up-to-date while keeping performance optimal, particularly with frequently changing datasets</p>
<h2>Benefits of incremental refresh</h2>
<p>Incremental refresh offers several benefits, particularly when dealing with large datasets in Power BI. Here are the main advantages:</p>
<ol>
<li><strong>Improved Performance</strong>: By only refreshing the most recent data partitions instead of the entire dataset, incremental refresh drastically reduces the time and resources needed during the refresh process.</li>
<li><strong>Efficient Data Handling</strong>: It minimizes the workload on both the server and network, leading to faster report availability and improved user experience, especially when using data sources that receive frequent updates.</li>
<li><strong>Cost-effective</strong>: For organizations using Power BI Premium, incremental refresh can lead to significant savings in compute resources, as less data processing time translates to lower costs.</li>
<li><strong>Reduced Load Times:</strong> Users can access reports with current data more quickly since only the new or changed data is processed, rather than waiting for large dataset refreshes.</li>
<li><strong>Better Management of Historical Data</strong>: It allows users to keep a subset of historical data while efficiently managing updates to the most recent data, which is particularly valuable for data models that rely on time-based analysis.</li>
<li><strong>Automation Capability</strong>: Incremental refresh is ideal for scheduled refreshes, allowing organizations to automate data updates at specific intervals without manual intervention.</li>
</ol>
<p>These benefits make incremental refresh a crucial feature for data analysts and organizations that need to work with large and frequently changing datasets in Power BI.</p>
<h2>Setting incremental refresh</h2>
<p>To set up incremental refresh in Power BI, follow these steps:</p>
<ol>
<li><strong>Prerequisites</strong>: Ensure you have Power BI Pro or Premium, as incremental refresh is not available in the free tier.</li>
<li><strong>Dataset Preparation</strong>:
<ul>
<li>Start by opening your Power BI Desktop and loading your dataset.</li>
<li>You may need to specify which table or data source will benefit from incremental refresh.</li>
</ul>
</li>
<li><strong>Define Parameters</strong>:
<ul>
<li>Create two parameters in Power Query:
<ul>
<li><em><strong>RangeStart</strong></em>: This parameter will define the start of the time range for data loading.</li>
<li><em><strong>RangeEnd</strong></em>: This parameter will define the end of the time range.</li>
</ul>
</li>
</ul>
</li>
<li><strong>Filter the Data</strong>:
<ul>
<li>After creating the parameters, apply a filter to your data query that uses these parameters to filter rows based on the date or time field that you want to use for incremental refresh.</li>
<li>For example, filter your data to include only records where your date field is greater than or equal to <em><strong>RangeStart</strong></em> and less than or equal to <em><strong>RangeEnd</strong></em>.</li>
</ul>
</li>
<li><strong>Configure Incremental Refresh</strong>:
<ul>
<li>Go to the "Modeling" tab in Power BI Desktop, and select "Manage Parameters" to set up incremental refresh policies.</li>
<li>Set how many periods of historical data you'd like to refresh and how many recent data snapshots you want to keep. For instance, you might want to keep the last 5 days of data but refresh daily.</li>
</ul>
</li>
<li><strong>Publish the Report</strong>:
<ul>
<li>Once you’ve set the parameters and filters, publish the report to Power BI Service.</li>
<li>The first time you publish, Power BI will load all data based on the defined range.</li>
</ul>
</li>
<li><strong>Define Refresh Plan in Service</strong>:
<ul>
<li>In Power BI Service, you can then set the refresh schedule for your dataset.</li>
<li>Any subsequent refreshes will honor the incremental refresh configuration you set up in Power BI Desktop, refreshing only the latest data.</li>
</ul>
</li>
</ol>
<p>Following these steps allows you to efficiently handle large datasets by only updating the necessary portions rather than the entire dataset.</p>
<h2>Set Up Incremental Refresh Step by Step</h2>
<h3>Step 1: Open a report into Power BI Desktop</h3>
<ul>
<li>Open Report in a Power BI Desktop</li>
<li>Click Home → Transform Data to open Power Query Editor</li>
</ul>
<p><img class="w-100" src="/media/DM/pbi-incremental-report.jpg"></p>
<h3>Step 2: Create Range Parameters</h3>
<ul>
<li>In the Power Query Editor, navigate to Manage Parameters —&gt; New Parameter.</li>
<li>Create two parameters:
<ul>
<li>RangeStart (Date/Time) — Set a default value (01.01.2020 0:00:00).</li>
<li>RangeEnd (Date/Time) — Set a default value (01.01.2021 0:00:00).</li>
</ul>
</li>
</ul>
<p><img class="w-100" src="/media/DM/pbi-incremental-parameters.jpg"></p>
<h3>Step 3: Apply Filters to the Data</h3>
<ul>
<li>Select the date column you want to filter by.
Click Filter —&gt; Custom Filter.</li>
<li>Set the filter condition:
<ul>
<li><em><strong>Greater than or equal</strong></em> to —&gt; RangeStart.</li>
<li><em><strong>Less than</strong></em> —&gt; RangeEnd.</li>
</ul>
</li>
<li>Click Close &amp; Apply to apply changes.</li>
</ul>
<p><img class="w-100" src="/media/DM/pbi-incremental-filter.jpg"></p>
<h3>Step 4: Enable Incremental Refresh</h3>
<ul>
<li>In Power BI Desktop, right-click the table —&gt; Incremental Refresh.</li>
<li>Configure settings:
<ul>
<li>Store data for (like 5 years).</li>
<li>Refresh data for (like the last 1 month).</li>
</ul>
</li>
<li>Click Apply.</li>
</ul>
<p><img class="w-100" src="/media/DM/pbi-incremental-apply.jpg"></p>
<h3>Step 5: Publish to Power BI Service</h3>
<ul>
<li>Click Publish and upload the report to the Power BI Service.</li>
<li>In Power BI Service, navigate to Dataset Settings —&gt; Refresh —&gt; Scheduled Refresh.</li>
</ul>
<p><img class="w-100" src="/media/DM/pbi-incremental-publish.jpg"></p>
<h3>Step 6: Test and Verify Refresh</h3>
<ul>
<li>Run a manual refresh to verify if only recent data updates.</li>
<li>Monitor refresh logs for errors.</li>
</ul>
<p><img class="w-100" src="/media/DM/pbi-incremental-check.jpg"></p>
<h2>Limitations of Power BI Incremental Refresh</h2>
<ul>
<li><strong>Requires a Premium or PPU License</strong>: Incremental Refresh in Dataflows is available only in Power BI Premium, Premium Per User (PPU), or Fabric capacities, and that makes it inaccessible for Pro users.</li>
<li><strong>Requires a Date/Time Column</strong>: Incremental refresh depends on a Date/Time column to filter new (or modified) data. If the dataset lacks such a column, you’ll need additional transformations before implementing it.</li>
<li><strong>Cannot Refresh Deleted Records</strong>: Incremental refresh only updates new (or modified) records but does not automatically handle deleted records unless designed using custom logic or soft delete.</li>
<li><strong>Limited Data Source Support</strong>: Not all data sources support incremental refresh. It typically works with SQL databases, certain cloud-based sources, and Azure. Direct API-based sources may not be compatible.</li>
</ul>
<h3>References:</h3>
<ul>
<li><a href="https://chartexpo.com/blog/power-bi-incremental-refresh#:%7E:text=Definition%3A%20Power%20BI%20Incremental%20Refresh%20optimizes%20data%20refreshes,ideal%20for%20handling%20large%20datasets%20in%20Power%20BI.">Power BI Incremental Refresh: A Complete Guide</a></li>
<li><a href="https://www.udemy.com/course/70-778-analyzing-and-visualizing-data-with-power-bi/?couponCode=CP251129CMG2">Udemy PL-300 certification prep</a></li>
</ul>
]]></description>
      <pubDate>Sun, 07 Dec 2025 19:08:20 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/pbi-incremental-refresh</guid>
    </item>
    <item>
      <title>Microsof Fabric as an all-in-one analytics solution</title>
      <link>https://radekrezac.dotnest.net/microsoft-fabric</link>
      <description><![CDATA[<p>In recent years, we have witnessed repeated transitions from centralized to decentralized governance and vice versa.  I have been involved in these changes, both in the corporate sphere in the IT field and in the field of IT solution providers.
In this article, I would like to take a closer look at the transition from decentralized Data Management to centralized using Microsoft Fabric solutions. Snowflake and Apache Spark Databricks are also moving in a similar direction.</p>
<h1>Centralized Data Management</h1>
<p>Centralized data involves gathering data from different sources and storing it in one central database, warehouse, and data lake. The data repository offers a centralized point for managing, storing, and using data, allowing for easier maintenance and management of data.</p>
<h1>Decentralized Data Management</h1>
<p>Decentralized Data involves the storage, cleaning, and use of data in a decentralized way. That is, there is no central repository. Data is distributed across different nodes, giving teams more direct access to data without the need for third parties.</p>
<h1>Comparison of Centralized versus Decentralized Data Management</h1>
<p><img class="w-100" src="/media/DM/comparison-datafabric-datamesh.jpg"></p>
<h1>Data Mesh</h1>
<p>is a <strong>decentralized approach to data architecture that promotes domain-oriented ownership and management of data</strong>. It advocates for treating data as a product, with each domain (or business unit) responsible for its own data pipelines, governance, and quality. The primary goal of data mesh is to address the limitations of traditional centralized data architectures by enabling scalability, agility, and autonomy of independent domains.</p>
<h1>Data Fabric</h1>
<p>is <strong>centralized aproach to data architecture and management</strong>. It is an end-to-end, unified analytics platform that <strong>brings together all the data and analytics tools that organizations need</strong>.</p>
<h1>Pros and Cons of Data Fabric</h1>
<p><img class="w-100" src="/media/DM/cons-pros-data-fabric.jpg"></p>
<h1>Microsoft Fabric</h1>
<p>Microsoft Fabric is Azure's solution for a centralized Data Fabric approach It’s designed to address the challenges of a fragmented data and AI technology market by <strong>integrating various technologies</strong> like Azure Data Factory, Azure Synapse Analytics, Power BI, and OpenAI Service <strong>into a single unified product</strong>.
This is a all in one analytic solution that is now covering everything from data movement to data science, real time analytics and business intelligence. And this includes everything from data lake, data engineering, data integration, Power BI, Real time analytics, and all of this is <strong>integrated in one environment</strong>. Everything is managed for us and we basically just use the software as it is (SaaS). We don't need to move the data between different tools, different services and different vendors.</p>
<h1>Microsoft Fabric Fundamentals</h1>
<h2>OneLake</h2>
<p>OneLake in Microsoft Fabric serves as the <strong>central data repository</strong>, functioning like a <strong>managed data lake</strong>. Here are the key aspects of OneLake:</p>
<ol>
<li><strong>Unified Storage</strong>: OneLake acts as a single, unified storage system for all your data assets. It simplifies data management by <em>consolidating storage in one place</em>, eliminating the need to piece together various tools and services.</li>
<li><strong>Data Accessibility</strong>: Rather than physically moving data from other locations (like AWS or Azure), OneLake allows you to create <em>shortcuts to external files</em>. This means you can access data without complex data pipelines, making your data management process more efficient.</li>
<li><strong>Integration</strong>: OneLake integrates seamlessly with other components in Microsoft Fabric, enabling various analytical processes without the typical barriers that exist in traditional tooling setups.</li>
<li><strong>Data Governance and Security</strong>: It includes features for data governance and security, ensuring your sensitive information is protected while providing access to authorized users within your organization.</li>
</ol>
<p>In summary, OneLake is a highly managed data lake as a service that allows users to store, access, and manage their data effectively within Microsoft Fabric.</p>
<p><img class="w-100" src="/media/DM/onelake.png"></p>
<h2>Workspace</h2>
<p>A workspace in Microsoft Fabric acts as a <strong>dedicated environment for managing and organizing data projects</strong>. Here are the key points about workspaces:</p>
<ol>
<li><strong>Segmentation</strong>: Think of a workspace as a folder or segment specifically designated for a certain project or department. This helps in organizing different types of workloads, such as data pipelines, reports, and analytics.</li>
<li><strong>Collaboration</strong>: Within a workspace, team members can collaborate on various items. The creator of a workspace typically controls who has access to it by adding users and assigning them specific roles (e.g., admin, member, contributor, or viewer).</li>
<li><strong>Creation of Items</strong>: In a workspace, you can create various data artifacts including but not limited to datasets, reports, data pipelines, notebooks, and dashboards. This allows for a comprehensive approach to data management and analysis.</li>
<li><strong>Capacity Assignment</strong>: Workspaces must be assigned to a specific capacity in Microsoft Fabric to utilize its features effectively. This capacity allows for the necessary computational power to handle the data operations within that workspace.</li>
</ol>
<p>Overall, a workspace serves as a central hub for conducting data-related activities in Microsoft Fabric, tailored to specific needs and collaborations.</p>
<p><img class="w-100" src="/media/DM/fabtic-workspace.png"></p>
<h2>Lakehouse</h2>
<p>A Lakehouse in Microsoft Fabric is an item created within a workspace that <strong>combines the functionalities of both data lakes and data warehouses.</strong> Here’s what you need to know about Lakehouses:</p>
<ol>
<li><strong>Hybrid Storage</strong>: A Lakehouse allows you to store various types of data, including structured data (like tables) and unstructured or semi-structured data (like CSV or JSON files). This flexibility makes it suitable for complex analytics workloads and machine learning projects.</li>
<li><strong>Delta Tables</strong>: Within a Lakehouse, you can create Delta Tables, which are optimized for high performance and support both batch and real-time data processing. This enhances analytics and reporting capabilities.
3.** Centralized Location**: The Lakehouse serves as a central location for storing, managing, and analyzing files and data. This integration makes it easier to connect with other tools and processes within Microsoft Fabric.</li>
<li><strong>Compatibility and Integration</strong>: The Lakehouse integrates seamlessly with various tools and technologies, including open-source technologies like Apache Spark and Delta Lake, facilitating advanced analytics and AI-driven insights.</li>
</ol>
<p>Overall, Lakehouses are designed to provide a flexible yet powerful data storage and management solution, bridging the gap between traditional data warehouses and modern data lakes.</p>
<p><img class="w-100" src="/media/DM/lakehouse.png"></p>
<h3>SQL Analytics Endpoint</h3>
<p>The SQL Analytics Endpoint in Microsoft Fabric is a <strong>connection interface that allows users to interact with their data stored in the Lakehouse using SQL queries</strong>*. Here are the key points regarding the SQL Analytics Endpoint:</p>
<ol>
<li><strong>Connection String</strong>: The SQL Analytics Endpoint provides a connection string which can be utilized to connect other tools, such as SQL Server Management Studio (SSMS) or Power BI, to the Lakehouse. This connection string facilitates accessing tables and executing SQL queries.</li>
<li><strong>Data Preview</strong>: Through the SQL Analytics Endpoint, users can explore the data structure within the Lakehouse. You can expand schemas and view tables (e.g., a sales table) directly, allowing you to preview data visually.</li>
<li><strong>Visual Interface</strong>: The endpoint offers a visual explorer, making it easier to navigate through your data without needing to write extensive queries initially. This interface helps users to become familiar with the structure of their datasets.</li>
<li><strong>Usage in BI Tools</strong>: The SQL connection can be utilized with BI tools like Power BI, enabling users to create reports and dashboards based on the data stored in the Lakehouse.</li>
<li><strong>Integration</strong>: The SQL Analytics Endpoint is part of the unified analytics architecture in Microsoft Fabric, ensuring that data is easily accessible and manageable within a single platform.</li>
</ol>
<p>In summary, the SQL Analytics Endpoint simplifies data interaction by providing a straightforward way for users to connect to their data and perform analytics using SQL language, enhancing the overall data management experience in Microsoft Fabric.</p>
<h4>Visual Query</h4>
<p>A visual query in Microsoft Fabric is a <strong>user-friendly tool that allows users, particularly those with less experience in SQL, to construct SQL queries using a graphical interface</strong> instead of writing code directly. Here are the key features and functionality:</p>
<ol>
<li><strong>Graphical Interface</strong>: Visual queries enable users to create and manipulate queries through a visual environment. This makes it easier to understand the relationships between different data elements and to build queries without extensive SQL knowledge.</li>
<li><strong>Ease of Use</strong>: The visual query tool is designed for ease, allowing users to drag and drop elements, select tables, and specify filters or joins without needing to understand complex SQL syntax.</li>
<li><strong>Accessing Visual Query Tool</strong>: To create a new visual query, users can click on a specific icon in the interface, which opens the visual query creation options. This makes it accessible for users who might not feel comfortable with traditional coding.</li>
<li><strong>Support for Beginners</strong>: Visual queries are particularly beneficial for individuals new to data analytics or SQL, allowing them to engage with data analysis without the technical overhead of writing SQL code.</li>
</ol>
<p>In summary, the visual query feature in Microsoft Fabric bridges the gap for users who are less familiar with SQL, providing a way to construct queries visually and efficiently.
<img class="w-100" src="/media/DM/visual-query.png"></p>
<h2>Shortcuts</h2>
<p>A shortcut in the context of Microsoft Fabric refers to a reference to a <em><strong>data table that allows you to access it without creating a redundant copy of the data</strong></em>. Here’s how it works:</p>
<ol>
<li><strong>Definition</strong>: A shortcut acts as a link to a data table, enabling you to interact with it just like a normal table while avoiding duplication.</li>
<li><strong>Creation</strong>:
<ol type="a">
<li>You can create a shortcut by selecting the table you want to reference and checking the appropriate option for creating a shortcut in your workspace.</li>
<li>This process allows you to connect to data from various sources, like SQL databases, and use it in a lakehouse without ingesting (copying) the data.</li>
</ol>
</li>
<li><strong>Benefits</strong>: Using shortcuts prevents unnecessary data storage and allows for seamless updates; any modifications made to the original table will be reflected when accessing it through the shortcut.</li>
<li><strong>Use Cases</strong>: Shortcuts are especially useful when you want to visualize or analyze data without the need for multiple copies, ensuring that your work remains efficient and organized.</li>
</ol>
<h2>Power BI Semantic Model</h2>
<p>The Power BI semantic model is essentially <em><strong>a data structure that organizes data and defines relationships between various tables, serving as a foundation for creating reports and visualizations</strong></em> in Power BI. Here’s a breakdown of its key aspects:</p>
<p><strong>Definition</strong>: Previously known as datasets, semantic models are created when you establish a lakehouse. They centralize data management, allowing seamless access and reporting.
<strong>Relationships</strong>: The semantic model maintains the relationships between different tables, which helps ensure data integrity and enables accurate data analysis in reports.
<strong>Usage</strong>: You can leverage the semantic model to create Power BI reports. When setting up a report, you can select an existing semantic model as the data source, allowing you to utilize the relationships and structures defined within it.
<strong>Measures</strong>: The semantic model can also include <em><strong>measures</strong></em>, which are theoretical calculations used within reports. These calculations aren’t stored physically but <em><strong>are computed on-the-fly when the report is run.</strong></em>
<strong>Performance and Efficiency</strong>: By using a semantic model, you avoid data redundancy since reports directly reference the centralized data in the lakehouse. This means there’s no unnecessary duplication of data, and performance can be optimized through well-structured queries.</p>
<p>Overall, a semantic model enhances the ability to create effective and insightful reports within Power BI, making data analysis more efficient and coherent.</p>
<h3>Semantic Model vs Tabular Model</h3>
<p>The Power BI semantic model and the tabular model are both crucial elements for data analysis but serve different purposes. Here’s a breakdown of their differences and similarities:</p>
<ol>
<li><strong>Definition</strong>:
<ul>
<li><em><strong>Power BI Semantic Model</strong></em>: This is a specific model used within Power BI that organizes and connects data from a lakehouse or other sources, allowing users to create reports seamlessly. It includes relationships between tables and serves as the foundation for visualizations.</li>
<li><em><strong>Tabular Model</strong></em>: This is generally used in SQL Server Analysis Services (SSAS) and serves as a dataset that can also operate within a multi-dimensional context. It focuses on in-memory caching for efficient querying and includes structured data in the form of tables and relationships.</li>
</ul>
</li>
<li><strong>Data Storage</strong>:
<ul>
<li><em><strong>Semantic Model</strong></em>: Data is referenced from a lakehouse, avoiding redundancy and maintaining efficient storage. Reports leverage the centralized dataset directly without duplicating data.</li>
<li><em><strong>Tabular Model</strong></em>: Data can be stored in-memory or queried directly from a relational database. It can involve data import that might create duplicates unless effectively managed.</li>
</ul>
</li>
<li><strong>Usage Context</strong>:
<ul>
<li><em><strong>Semantic Model</strong></em>: It is preferred for storage efficiency and centralized data management when creating reports directly in the Power BI service. Reports directly leverage this existing model.</li>
<li><em><strong>Tabular Model</strong></em>: It is often used in more advanced modeling scenarios requiring robust transformations before publishing, usually managed within a local environment like Power BI Desktop.</li>
</ul>
</li>
<li><strong>Performance</strong>:
<ul>
<li><em><strong>Semantic Model</strong></em>: Performance can depend on whether direct query or import mode is used. It’s structured to optimize data access efficiently.</li>
<li><em><strong>Tabular Model</strong></em>: It generally provides fast query performance through in-memory data caching, but it may require additional management to optimize performance for reporting.</li>
</ul>
</li>
<li><strong>Relationships</strong>:
<ul>
<li>Both models maintain relationships between tables, essential for accurate reporting, but the management methodologies can differ. Power BI's semantic model can automatically infer relationships, making it easier to create actionable insights.
In conclusion, while both models allow structured data interaction, the <strong>Power BI semantic model focuses on i</strong>ntegration and efficiency within the <strong>Power BI ecosystem</strong>, while the <strong>tabular model</strong> is broader, used primarily <strong>in various analytical contexts</strong>.</li>
</ul>
</li>
</ol>
<h3>Row Level Security (RLS)</h3>
<p>Row-level security in Power BI is a feature that allows you to restrict data access for specific users or groups. This means <strong>different users can see different data in the same report</strong> based on their roles or permissions. Here’s how it works:</p>
<p><strong>Roles Creation</strong>: You define roles within your Power BI model. Each role specifies a filter that determines what data is visible to people assigned to that role. For instance, a manager might see all data, while an employee might only see their own department's data.
<strong>DAX Filters</strong>: You can use Data Analysis Expressions (DAX) to specify access rules. This involves writing DAX expressions that evaluate the current user and filter the data accordingly.
<strong>User Assignment</strong>: After defining roles, you assign users to these roles either in Power BI Desktop for testing or in the Power BI service when publishing the report.
Dynamic Filtering: RLS can also use dynamic filtering based on the user’s identity. This means you can automatically filter the data shown to the user based on their login credentials, which can be obtained through functions like USERNAME(), USERPRINCIPALNAME(), or ISINSCOPE().</p>
<p>Implementing <strong>RLS helps protect sensitive data and ensures that users see only the information relevant to them</strong>, enhancing data privacy and compliance.</p>
<h2>Warehouse</h2>
<p>A warehouse, in the context of data analytics, refers to a <strong>specialized layer designed for high-performance analytics and reporting</strong> on structured data. It is primarily optimized for structured data, such as relational data sourced from databases, and utilizes SQL for querying and analysis.</p>
<p>To break it down further:</p>
<ol>
<li><strong>Purpose</strong>: Data warehouses provide strategic insights by consolidating and managing data from multiple sources, making them essential for business intelligence and reporting purposes.</li>
<li><strong>Data Structure</strong>: They are designed to handle structured data, which is organized in a format that is easily accessible and analyzable.
3.<strong>Integration with OneLake and Lakehouse</strong>: In Microsoft Fabric, data warehouses function within a broader framework that includes OneLake (a unified storage system) and Lakehouse (which combines the features of data lakes and data warehouses). This means that data warehouses can access data stored in OneLake and are suitable for performing complex analytics workloads.</li>
<li><strong>Performance</strong>: They are optimized for high-performance needs, meaning they can handle large volumes of data efficiently, making them suitable for businesses that require timely and accurate data analysis.</li>
</ol>
<p>In summary, a warehouse is integral for organizations that need to perform robust analytics and reporting on structured data, enabling informed decision-making based on comprehensive data insights.</p>
<h3>Diference between Lakehouse and Warehouse</h3>
<p>The main differences between a lakehouse and a warehouse can be summarized as follows:</p>
<ol>
<li><p><strong>Data Types Supported</strong>:</p>
<ul>
<li><em><strong>Lakehouse</strong></em>: Supports structured, semi-structured, and unstructured data, making it ideal for diverse data types. It allows the storage of files such as CSV or JSON alongside structured tables, providing flexibility in data management.</li>
<li><em><strong>Warehouse</strong></em>: Primarily designed for structured data, such as relational data from databases. It is optimized specifically for high-performance analytics and reporting tasks.</li>
</ul>
</li>
<li><p><strong>Architecture and Flexibility</strong>:</p>
<ul>
<li><em><strong>Lakehouse</strong></em>: Combines the advantages of data lakes and warehouses, allowing for both rigid structured tables and flexible file storage. It supports real-time and batch processing for complex analytics workloads, machine learning, and data science projects.</li>
<li><em><strong>Warehouse</strong></em>: A specialized layer focused on high-performance analytics tailored for structured queries, making it familiar for traditional data analysts.</li>
</ul>
</li>
<li><p><strong>Query Capabilities</strong>:</p>
<ul>
<li><em><strong>Lakehouse</strong></em>: Can be queried through a SQL endpoint, but it is read-only when using SQL, meaning you cannot perform write or update operations via SQL queries.</li>
<li><em><strong>Warehouse</strong></em>: Allows for both read and write operations, making it suitable for executing complex queries and data updates.</li>
</ul>
</li>
<li><p><strong>Use Cases</strong>:</p>
<ul>
<li><em><strong>Lakehouse</strong></em>: Best suited for projects involving machine learning, real-time analytics, and processing diverse data formats. It serves as a centralized location for managing and analyzing various data types.</li>
<li><em><strong>Warehouse</strong></em>: Ideal for organizations focusing on high-performance reporting and analytics tasks that rely heavily on structured data.</li>
</ul>
</li>
</ol>
<p>In summary, the lakehouse offers a more flexible and comprehensive approach to data management, while the warehouse is specialized for efficient and performant analytics solely on structured data.</p>
<p><img class="w-100" src="/media/DM/lakehouse-warehouse.jpg"></p>
<h3>Underlying format</h3>
<p>The underlying format of a warehouse, particularly in the context of Microsoft Fabric, involves the use of the <strong>Delta Parquet</strong> format for data storage. Here are the key points related to its underlying format:</p>
<ol>
<li><strong>Delta Tables</strong>: Warehouses utilize delta tables, which are built on the Parquet format. This allows for efficient data processing and storage. Delta tables <strong>provide features like ACID transactions</strong>, efficient data updates, and schema enforcement, enhancing the reliability of data operations.</li>
<li><strong>Integration with OneLake</strong>: The warehouse operates within the OneLake storage system, which serves as a unified storage solution. This integration enables warehouses to access and utilize data stored across different formats and sources.</li>
<li><strong>SQL Support</strong>: The data warehouse environment also facilitates the use of <em><strong>T-SQL</strong></em> (Transact-SQL) for creating and managing tables, as well as for running analytics queries. This is a critical feature that distinguishes it from other components like lakehouses, where direct table creation is not supported.</li>
<li><strong>Performance Optimization</strong>: The warehouse is specifically optimized for high-performance analytics and reporting on structured data, making it suitable for traditional BI use cases.</li>
</ol>
<p>In summary, the warehouse is constructed around delta tables in the Parquet format and is designed to deliver high-performance query capabilities while facilitating robust data management features.</p>
<h2>Apache Spark</h2>
<p>Apache Spark offers several strengths that make it a powerful tool for <strong>data processing and analytics</strong>:</p>
<ol>
<li><strong>Distributed Computing</strong>: Spark is designed to operate across a <em><strong>network of machines</strong></em>, allowing it to efficiently handle large datasets and complex data processing tasks. This distributed nature means computations are executed in parallel, making it much faster than processing on a single machine.</li>
<li><strong>In-Memory Processing</strong>: By caching <em><strong>data in memory instead of relying on disk reads</strong></em>, Spark significantly speeds up data processing. This enables quicker access and manipulation of data, which is vital for real-time applications.</li>
<li><strong>Resilient Distributed Datasets (RDDs)</strong>: Spark's core abstraction for handling data is RDDs, which are fault-tolerant collections of data partitions distributed across the cluster. RDDs ensure that data can be recovered from errors, maintaining data integrity and processing performance.</li>
<li><strong>Flexibility with Programming Languages</strong>: Spark supports <em><strong>multiple programming languages</strong></em>, including Scala, Python, and Java. This flexibility allows data engineers and data scientists to choose a language they are comfortable with, facilitating easier development.</li>
<li><strong>Support for Both Batch and Real-Time Processing</strong>: Spark can handle both batch processing and streaming data, making it versatile for different types of analytics tasks.</li>
<li><strong>Integration with Machine Learning</strong>: Spark includes libraries for machine learning, data science, and graph processing, enabling advanced analytics directly within the framework.</li>
<li><strong>Optimized for Large-Scale Data Operations</strong>: It is well-suited for processing large amounts of data efficiently, making it an ideal choice for large-scale ETL processes and analytics.</li>
</ol>
<p>These strengths position Apache Spark as a vital tool in the toolkit of data scientists and engineers, especially when working with large and complex data environments.</p>
<p><img class="w-100" src="/media/DM/apache-spark.png"></p>
<h3>Loading data from a lakehouse</h3>
<p>To load data from a lakehouse into a DataFrame using Databricks, you can follow these steps:</p>
<ul>
<li><strong>Set Up Your Environment</strong>: Make sure you have access to the lakehouse in Databricks.</li>
</ul>
<p><img class="w-100" src="/media/DM/add-lakehouse-2-databricks.jpg"></p>
<ul>
<li><strong>Load Data</strong>: Use Spark's read functionality to load data into a DataFrame. The syntax generally looks like this:</li>
</ul>
<pre><code class="language-python"># Inferring the Schema Automatically

df = spark.read.format("csv") \
    .option("header", "true") \
    .option("inferSchema", "true") \
    .load("lakehouse_path")
</code></pre>
<p>Replace <code>lakehouse_path</code> with the actual path to your file in the lakehouse.</p>
<ul>
<li><p><strong>Adjust Options as Needed</strong>: Depending on your data format (e.g., CSV, JSON, Parquet), you might need to adjust the <code>.format</code> and include other options, such as delimiters or schema definitions.</p>
</li>
<li><p><strong>Work with Your DataFrame</strong>: After loading the data, you can perform various operations such as showing some rows, processing, or analyzing data:</p>
</li>
</ul>
<pre><code>df.show()
</code></pre>
<ul>
<li><strong>Error Handling (Optional)</strong>: If there’s an error loading the DataFrame, review the path and format options to ensure everything is correctly specified.</li>
</ul>
<h3>Writing a DataFrame back to a lakehouse</h3>
<ul>
<li><p><strong>Prepare Your DataFrame</strong>: Ensure you have the DataFrame ready that you want to write to the lakehouse.</p>
</li>
<li><p><strong>Write as a Delta Table</strong>: The preferred method for storing data in a lakehouse is as a Delta table. This allows for optimized performance and compatibility with tools like Power BI. You can use the following code snippet:</p>
</li>
</ul>
<pre><code class="language-python">df.write.format("delta").saveAsTable("tablename")
</code></pre>
<p>Replace <code>tablename</code> with the name you want to assign to your table in the lakehouse.</p>
<ul>
<li><strong>Write as a CSV File (Alternative Option)</strong>: If you prefer to write the DataFrame as a file, such as a CSV, you can use:</li>
</ul>
<pre><code>df.write.csv("lakehouse_path")
</code></pre>
<p>Here, replace <code>lakehouse_path</code> with the path where you want to save the CSV file. Databricks will create the necessary directories if they do not exist.</p>
<ul>
<li><p><strong>Check the Path</strong>: For the CSV option, ensure that the path you specify is correct, as that is where the output file will be generated.</p>
</li>
<li><p><strong>Verify the Write Operation</strong>: After the write operation, you can verify that the data has been saved correctly by reading it back into a DataFrame using:</p>
</li>
</ul>
<pre><code class="language-python">new_df = spark.read.format("delta").load("lakehouse_path")
</code></pre>
<h3>Temporary views</h3>
<p>To create and use temporary views in a Databricks notebook, follow these steps:</p>
<ul>
<li><strong>Create Temporary Views</strong>: You can create a temporary view using the createOrReplaceTempView method. For example, if you have a DataFrame called sales, you can create a temporary view like this:</li>
</ul>
<pre><code class="language-python">sales.createOrReplaceTempView("sales_temp_view")
</code></pre>
<ul>
<li><strong>Query the Temporary View</strong>: After creating the temporary view, you can run SQL queries against it. For instance:</li>
</ul>
<pre><code class="language-Python">result = spark.sql("SELECT * FROM sales_temp_view")
result.show()
</code></pre>
<ul>
<li><p><strong>Session Scope</strong>: Keep in mind that temporary <em><strong>views are session-scoped</strong></em>; they will only exist during the active notebook session. Once the session ends, the view will no longer be accessible.</p>
</li>
<li><p><strong>Use Multiple Views</strong>: You can create multiple temporary views from different DataFrames. For example, if you have another DataFrame called products, you can create a temporary view for it as well:</p>
</li>
</ul>
<pre><code class="language-Python">products.createOrReplaceTempView("products_temp_view")
</code></pre>
<ul>
<li><strong>Combine Queries</strong>: Temporary views allow you to run complex SQL queries involving multiple views and DataFrames, combining the power of Spark with SQL syntax for more flexibility.
This approach enables effective data manipulation and querying without the need for permanent storage, facilitating quick data analysis within your current session.</li>
</ul>
]]></description>
      <pubDate>Sun, 07 Dec 2025 19:07:31 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/microsoft-fabric</guid>
    </item>
    <item>
      <title>Set Power BI Row-Level Security to SAP Cost Center</title>
      <link>https://radekrezac.dotnest.net/data-ai/power-bi-row-level-security</link>
      <description><![CDATA[<p>In organizations where data is shared between different departments, it is crucial to restrict access to only the information that is necessary. To this end, Microsoft Power BI offers <strong>Row-Level Security (RLS)</strong> and <strong>Object-Level Security (OLS)</strong>.</p>
<h2>Row-Level Security</h2>
<p>Row-Level Security (RLS) is a security feature in Power BI that restricts access to rows in a table based on the identity of the user viewing the report. Rather than duplicating reports for different user groups, <strong>RLS allows you to apply filters at the data level</strong> so that each user sees only the data they are permitted to view.</p>
<p>This is crucial for preserving data confidentiality and integrity, especially in scenarios involving sensitive or proprietary information. RLS operates within the Power BI data model and ensures that unauthorized users cannot access restricted data, even through indirect methods such as slicers or drill-downs.</p>
<h3>Setting Role-level security :</h3>
<ol>
<li><strong>Create Roles</strong>: Use DAX (Data Analysis Expressions) or logical statements to define roles that filter the data. For example, you might create a role for "Territory Managers" that only allows them to see data for their respective territories.</li>
<li><strong>Testing</strong>: After setting up the roles, test them within Power BI Desktop using the "<em><strong>View As</strong></em>" feature to ensure that the data is being filtered correctly according to the defined roles.</li>
<li><strong>Deployment</strong>: Finally, publish the report to the Power BI service and confirm the RLS configurations are working as expected in that environment.</li>
</ol>
<h3>Static vs Dynamic RLS Architectures</h3>
<p>Row-level security can be split into two types: <strong>static</strong> and <strong>dynamic</strong>.</p>
<h4>Static RLS implementation</h4>
<p>Static RLS involves creating roles with <strong>hardcoded DAX filters</strong>. Each role corresponds to a specific group or segment, such as a geographic region or department.</p>
<p>Here are the general steps to implement a static RLS:</p>
<ol>
<li>Create a role named, e.g., "Region_East."</li>
<li>Apply a filter such as [Region] = "East" to that role.</li>
<li>Assign specific users to the role in Power BI Service.</li>
</ol>
<h4>Dynamic RLS implementation</h4>
<p>Dynamic RLS uses functions like USERNAME() or USERPRINCIPALNAME() combined with mapping tables to dynamically filter data based on user identity.</p>
<p>Here are the general steps to implement a dynamic RLS:</p>
<ol>
<li>Create a mapping table linking users to access levels. This will be your security table. This table should include columns like user emails, their access regions, and their names.</li>
<li>Write a DAX filter like: [Region] = RELATED(UserRegion[Region])</li>
<li>Filter that table with: UserRegion[Email] = USERPRINCIPALNAME()</li>
</ol>
<h2>Example: RLS based on SAP roles granted to user</h2>
<p>The basis for setting rights are SAP tables containing information about cost centers assigned to individual users via business roles.
The resulting authorization table obtained from the above SAP tables contains both the <strong>email address</strong> matching the <strong>logged-in user</strong> and the assigned <strong>cost centers</strong>. The user's email address appears multiple times for each assigned cost center:</p>
<p><img class="w-100" src="/media/DM/rls-authorization.jpg"></p>
<p>Dynamic RLS uses function <strong>USERPRINCIPALNAME()</strong> as a logged-in user and apply filter on Table <strong>Cost Center</strong>:</p>
<pre><code>VAR Logged_User =

   LOWER(USERPRINCIPALNAME ())

RETURN

       CALCULATE (

           COUNTROWS ( 'Cost Center' ),

           'Cost Center'[Cost Center Key]

               IN CALCULATETABLE (

                   VALUES ( Authorization[Cost Center] ),

                   FILTER ( ALL ( Authorization), [User Email] =  Logged_User )

               )

       ) &gt; 0
</code></pre>
<p>The logged-in user then sees only data that is linked to the assigned cost centers.</p>
<p><img class="w-100" src="/media/DM/rls-costcenter.jpg"></p>
]]></description>
      <pubDate>Sun, 07 Dec 2025 19:05:47 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/data-ai/power-bi-row-level-security</guid>
    </item>
    <item>
      <title>Dynamic Management Views (DMVs) </title>
      <link>https://radekrezac.dotnest.net/dax-dmv</link>
      <description><![CDATA[<h2>DMVs</h2>
<p>Dynamic Management Views (DMVs) are special system views that expose i<strong>nternal server state for monitoring and troubleshooting</strong>.
You can join DMVs together, but there are some limitations depending on the context:</p>
<ol>
<li><strong>SQL Server DMVs</strong>: (like sys.dm_exec_sessions, sys.dm_exec_requests) support normal JOIN syntax.</li>
<li><strong>Analysis Services DMVs</strong>: (like DISCOVER_SESSIONS) have a restricted SQL-like syntax and do not support JOIN — you must query separately and join in your application code.</li>
</ol>
<h3>Analysis Services DMVs</h3>
<p>Here’s a breakdown of what Analysis Services DMVs are and how they're useful:</p>
<ol>
<li><strong>Purpose of DMVs</strong>: DMVs allow users to retrieve metadata about objects in a model, such as tables, relationships, and hierarchies. They help in understanding how data is structured and managed.</li>
<li><strong>Types of Information</strong>: DMVs can provide details about <strong>table relationships</strong>, data <strong>partitions</strong>, <strong>hierarchies</strong>, and compatibility levels of models. This information is crucial for analysis and optimization of the data models.</li>
<li><strong>Querying DMVs</strong>: You can query DMVs directly using tools like SQL Server Management Studio (SSMS) or DAX Studio. This querying allows you to gather comprehensive data about your model’s schema and performance metrics.</li>
<li><strong>Usefulness in Analysis</strong>: By utilizing DMVs, users can gain better insights into models that might not be immediately visible in graphical tools like Power BI. Some tables created by Power BI, for example, may not appear directly in the interface but can be accessed through DMVs.</li>
</ol>
<p>Understanding and executing queries on DMVs can greatly enhance your ability to manage your data effectively and improve your data model's performance.</p>
<h3>Query DMV in DAX studio</h3>
<p>To query Dynamic Management Views (DMVs) in DAX Studio, you can follow these steps:</p>
<ol>
<li><strong>Connect to Your Model</strong>: Start by connecting to your data model in DAX Studio. Ensure that you are connected to the appropriate instance of Analysis Services that contains your data model.</li>
<li><strong>Access the DMV Tab</strong>: Once connected, navigate to the 'DMV' tab within DAX Studio. This tab provides access to various DMVs available in your connected model.</li>
<li><strong>Execute DMV Queries</strong>: Type in the desired DMV query to retrieve metadata about your model. For instance, you can use the DISCOVER_SESSIONS DMV to gather session-related information or the DISCOVER_CATALOGS-view catalog details. You may also use the tables and columns DMVs to understand the structure of your model.</li>
<li><strong>Review Results</strong>: After executing the query, you can view the results directly in DAX Studio. This allows you to analyze the output, which may include component names and hierarchical relationships that are not visible through standard Power BI interfaces.</li>
<li><strong>Consider Limitations</strong>: Keep in mind that while DMVs are valuable for inspecting your models, some features might be better realized through <em><strong>SQL Server Management Studio (SSMS)</strong></em>. For certain advanced queries, you may need to enable ad hoc distributed queries by using the <code>sp_configure</code> command as outlined in the course.</li>
</ol>
<p><strong>Zde jsou nejčastější dotazy na DMV</strong>:</p>
<pre><code class="language-sql">-- Query to retrieve all tables in a model
select * from $SYSTEM.TMSCHEMA_TABLES

-- Query to get all columns (note the SortByColumnId column)
Select * From $SYSTEM.TMSCHEMA_COLUMNS

-- Query to get all calculated columns
Select * From $SYSTEM.TMSCHEMA_COLUMNS Where [Type] = 2

-- Query to get all measures
select * from $SYSTEM.TMSCHEMA_MEASURES

-- Query to get all dependencies
select * from $system.discover_calc_dependency

-- Get unique row counts for all tables and columns
select * from $SYSTEM.DISCOVER_STORAGE_TABLES order by rows_count desc

-- Query to get all the roles, associated permissions and role memberships defined in the model
select * from $SYSTEM.TMSCHEMA_Roles
select * from $SYSTEM.TMSCHEMA_TABLE_PERMISSIONS
select * from $SYSTEM.TMSCHEMA_Role_Memberships

-- Query to get all the KPIs defined in the model
select * from $SYSTEM.TMSCHEMA_KPIS

-- Query to get session information
select * from $SYSTEM.DISCOVER_SESSIONS

-- Query to get all relationships
select * from $SYSTEM.TMSCHEMA_RELATIONSHIPS

-- Queries to get hierarchy information
select * from $SYSTEM.TMSCHEMA_ATTRIBUTE_HIERARCHIES
select * from $SYSTEM.TMSCHEMA_ATTRIBUTE_HIERARCHY_STORAGES

-- Query to get information about each model:
select * from $SYSTEM.TMSCHEMA_MODEL

-- Query to get information about each partition:
select * from $SYSTEM.TMSCHEMA_PARTITIONS

-- Query to get perspective information:
select * from $SYSTEM.TMSCHEMA_PERSPECTIVES

-- Query to get catalog information (especially compatibility level):
select * from $SYSTEM.DBSCHEMA_CATALOGS 
</code></pre>
<h3>Query DMV in SSMS</h3>
<p>To use Dynamic Management Views (DMVs) in SQL Server Management Studio (SSMS), follow these steps:</p>
<ol>
<li><strong>Connect to SQL Server</strong>: Open SSMS and connect to your SQL Server instance. If you're using Analysis Services, select "Connect" and choose "Analysis Services," entering the appropriate server name and port if necessary.
2.<strong>Open a New Query Window</strong>: Once connected, navigate to the "New Query" option to start writing your SQL queries. If you are getting prompts for MDX queries, ensure you are connected to the right service.</li>
<li><strong>Query DMVs</strong>: You can write SQL queries to access DMVs. For example, you may want to look up the DISCOVER_SESSIONS or DISCOVER_CATALOGS DMVs which provide session details and catalog information, respectively.</li>
<li><strong>Enable Ad Hoc Distributed Queries</strong>: If you plan to use OPENROWSET to access DMVs, make sure that ad hoc distributed queries are enabled on your SQL instance. You can do this by executing:</li>
</ol>
<pre><code class="language-sql">EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'Ad Hoc Distributed Queries', 1;
RECONFIGURE;
</code></pre>
<ol start="5">
<li><strong>Run Your Query</strong>: Execute your query to see the results. This will allow you to retrieve useful information about your model that might not be visible through other means.</li>
</ol>
<p>This approach allows you to use JOIN to connect, for example, a view with columns and a view with tables:</p>
<pre><code class="language-sql">------------------------------------------------------------------------------------------------------
-- This query establishes a connection to the SSAS server represented in the OPENROWSET connection
-- string field and the catalog references in the connection string. It then pulls table and column
-- information 
------------------------------------------------------------------------------------------------------

-- It may be necessary to execute these statements first.
sp_configure 'show advanced options', 1;  
RECONFIGURE;
GO 

sp_configure 'Ad Hoc Distributed Queries', 1;  
RECONFIGURE; 
GO

-- Query the table and column data in the model or models.
;WITH [Tables] AS
(
	SELECT 
		ID as TableId
		,ModelId
		,[Name] as TableName
		,DataCategory
		,[Description] as Description
		,IsHidden								-- Is the table treated as hidden by a client visualization tool
		,ModifiedTime							-- The time the table was last modified
		FROM OPENROWSET('MSOLAP','DATASOURCE= localhost:60921; Initial Catalog=4f655bd0-716b-4bf6-9424-727ec45e4b47;','SELECT * FROM $SYSTEM.TMSCHEMA_TABLES')
)

,[Columns] AS
(
SELECT 
	ID as Id
	,TableId
	,ExplicitName as ColumnName
	,InferredName																					-- Engine generated name (Calculated columns only)
	,CASE
		When ExplicitDataType = 1 Then 'Automatic'
		When ExplicitDataType = 2 Then 'String'
		When ExplicitDataType = 6 Then 'Int64'
		When ExplicitDataType = 8 Then 'Double'
		When ExplicitDataType = 9 Then 'DateTime'
		When ExplicitDataType = 10 Then 'Decimal'
		When ExplicitDataType = 11 Then 'Boolean'
		When ExplicitDataType = 17 Then 'Binary'
		When ExplicitDataType = 19 Then 'Unknown'
		Else 'N/A'
	 END as DataType
	,DataCategory
	,Description
	,IsHidden																						-- Treated as hidden by a client visualization tool?
	,IsUnique																						-- Can the column contain duplicate values?
	,IsKey																							-- Is the column a key of the table?
	,IsNullable																						-- Can the column contain null values?
	,CASE
		WHEN T.Type = 1 Then 'From data source'
		WHEN T.Type = 2 Then 'Calculated'
		WHEN T.Type = 3 Then 'Row number'
		ELSE 'N/A'
	END as ColumnType
	,SourceColumn																					-- Source column name
	,Expression																						-- The calculated column DAX expression
	,FormatString																					-- String controlling the formatting of the column
	,SortByColumnId																					-- Specifies the column that is controlling the sorting of this column
	,AttributeHierarchyId																			-- A reference to an AttributeHierarchy object
	,ModifiedTime																					-- The time the column was last modified
	,ErrorMessage																					-- A string explaining the error state of the column
	FROM OPENROWSET('MSOLAP','DATASOURCE= localhost:60921; Initial Catalog=4f655bd0-716b-4bf6-9424-727ec45e4b47;','SELECT * FROM $SYSTEM.TMSCHEMA_COLUMNS') T
)

Select 
	T.TableName, 
	T.ModelId, 
	C.*, 
	ISNULL(C2.ColumnName,'') as SortByColumnName
From Tables T
	Inner Join Columns C ON T.TableId = C.TableId
	Left Join Columns C2 ON C2.Id = C.SortByColumnId
</code></pre>
<p><strong>Of course, when selecting from OPENROWSET, you must replace DATASOURCE for your model.</strong></p>
]]></description>
      <pubDate>Sun, 07 Dec 2025 19:03:18 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/dax-dmv</guid>
    </item>
    <item>
      <title>Orchard Core Shapes</title>
      <link>https://radekrezac.dotnest.net/orchard-core-shape</link>
      <description><![CDATA[<p>Orchard Core doesn't render HTML directly, but instead will usually render something called a <strong>Shape</strong>, which is an object that represents the thing to render and has all the necessary data and metadata to render HTML.
When rendering a Shape, Orchard Core will look for specific <strong>templates</strong>, passing the Shape to this template.
Orchard Core can match with many templates for the same Shape. These potential templates are called <strong>Alternates</strong>.</p>
<h2>What is a Shape</h2>
<ul>
<li>An object implementing the <strong>IShape</strong> interface</li>
<li>A <strong>dynamic</strong> data model that contains:
<ul>
<li><strong>Data</strong> that will be <em><strong>rendered</strong></em> by ASP.NET views</li>
<li><strong>Metadata</strong> on <em><strong>how</strong></em> to render it</li>
</ul>
</li>
</ul>
<h2>Benefits of Shapes</h2>
<ul>
<li>No view name is hard-codded - view name is based on a shape</li>
<li>Priority based view resolution - Alternates</li>
<li>Theming - User defined Templates (views)</li>
<li>Dynamic caching</li>
<li>Wrapping</li>
<li>Placement
<ul>
<li>Zones</li>
<li>Ordering</li>
</ul>
</li>
<li>Multiple sources
<ul>
<li>Database</li>
<li>Files</li>
<li>Code</li>
</ul>
</li>
<li>Events</li>
</ul>
<h2>Creating and rendering shapes</h2>
<ol>
<li>Create a shape by shape factory and name it
<ul>
<li><code>	var factory = context.RequestServices.GetREquiredService&lt;IDisplayHelper&gt;();</code></li>
<li><code> var shape = await factory.CreateAsync("Car");</code></li>
</ul>
</li>
<li>Create a HTML content by display helper
<ul>
<li><code> var displayHelper = context.RequestServices.GetRequiredService&lt;IDisplayHelper&gt;();</code></li>
<li><code> var htmlContent = await displayHelper.ShapeExecuteAsync(shape);</code></li>
</ul>
</li>
<li>Create a view according to shape name : <code>Car.cshtml</code></li>
<li>Send a HTML conent to Response Body
<ul>
<li><code> await using var sw = new StreamWriter(context.Response.Body);</code></li>
<li><code> htmlContent.WriteTo(sw, HtmlEncoder.Default);</code></li>
</ul>
</li>
</ol>
<p>Code is available on Github in the branch: <a href="https://github.com/radekrezac/DemystifyingShapes/tree/Test_Shape_With_Razor_View">Test_Shape_With_Razor_View</a></p>
<h2>Rendering shapes with Liquid templates</h2>
<p>Liquid is a safe, customer-facing templating language originally created by <a href="https://shopify.github.io/liquid/">Shopify</a>. It's designed to be <strong>secure</strong>, <strong>flexible</strong>, and easy to understand, making it <strong>perfect for generating dynamic content</strong> where you need to combine static templates with variable data from your application.
To render shapes using a liquid templates we only add to dependencies <code>OrchardCore.DisplayManagement.Liquid</code> package and to Program.cs <code>AddLiquidViews()</code> service.</p>
<h2>Add data to shapes</h2>
<p>The shape as an instance of the <strong>IShape</strong> interface contains the <code>Properties</code> property of type <code>IDictionary</code>, where we can insert data via the index, which is then visible in the template. In the template, then we display data using the 'Model' object. The <code>ShapeExecuteAsync</code> method sends a <code>Shape</code> model to the template, which, in addition to <code>IShape</code>, is also an instance of the <code>DynamicObject</code> class of <code>Compose</code> containing the <code>TryGetMember</code> method. This allows us to access Properties directly, e.g., <code>Model.Brand</code> instead of <code>Model.Properties["Brand"]</code>.</p>
<p>Code for this part is available on Github in the branch: <a href="https://github.com/radekrezac/DemystifyingShapes/tree/Test_ShapeData_With_Liquid_Template">Test_ShapeData_With_Liquid_Template</a></p>
<h2>Strongly typed shapes</h2>
<p>Since the dynamic approach requires some overhead, we will use a generic method <code>CreateAsync</code> to create the shape and use a POCO object as the type. In our case, the <code>Car</code> class.</p>
<pre><code class="language-csharp">public class Car
{
    public string? Brand { get; set; }
    public string? Color { get; set; }
}
var shape = await factory.CreateAsync&lt;Car&gt;("Car", c =&gt; { c.Brand = "Renault"; c.Color = "Red";});
</code></pre>
<p>Now we can type the model as Car and get the value directly from the class properties:</p>
<pre><code class="language-csharp">@using OrchardCore.DisplayManagement;
@model Car

This is a car @Model.Brand with @Model.Color color
</code></pre>
<h2>Adding metadata to a shape</h2>
<p>As mentioned 'IShape' contains metadata, like <code>Id</code>, <code>TagName</code>, <code>Classes</code>, <code>Attributes</code>... , that can be used to render a shape by template. In a template we then render these metadata with helper class. Here is code setting metadata</p>
<pre><code class="language-csharp">   shape.Id = "my-renault";
   shape.TagName = "h3";
   shape.Classes.Add("car");
   shape.Classes.Add("brand-renault");
   shape.Attributes.Add("data-brand", "renault");
</code></pre>
<p>and here templates rendering them:</p>
<pre><code class="language-csharp">@using OrchardCore.DisplayManagement;
@model Car

@{
    var shape = Model as IShape;
    var tagBuilder = shape.GetTagBuilder();
}

@tagBuilder.RenderStartTag()
This is a car @Model.Brand with @Model.Color
@tagBuilder.RenderEndTag()
</code></pre>
<p>The result is this content:
<img src="/media/OC/rendered-car.jpg"></p>
<p>and if we look at the HTML code, we can see the rendered shape metadata:
<img src="/media/OC/rendered-car-source.jpg"></p>
<p>Code for this part is available on Github in the branch: <a href="https://github.com/radekrezac/DemystifyingShapes/tree/Test_Shape_With_Metadata">Test_Shape_With_Metadata</a></p>
<h2>References:</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=yaZhKuD2qoI&amp;list=PLpCsCyd254FpDNAMH_Pat0YADI2jMWTTT&amp;index=6">Orchard Harvest 2024: Demystifying Shapes, Part 1</a></li>
</ul>
]]></description>
      <pubDate>Sun, 07 Dec 2025 19:07:42 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/orchard-core-shape</guid>
    </item>
    <item>
      <title>General Delta Table processing</title>
      <link>https://radekrezac.dotnest.net/general-delta-table</link>
      <description><![CDATA[<p>Python is an object-oriented programming language, and it supports the four main pillars of OOP: encapsulation, inheritance, polymorphism, and abstraction.</p>
]]></description>
      <pubDate>Sun, 07 Dec 2025 19:07:54 GMT</pubDate>
      <guid isPermaLink="true">https://radekrezac.dotnest.net/general-delta-table</guid>
    </item>
  </channel>
</rss>