<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Moses Favour</title>
    <description>The latest articles on DEV Community by Moses Favour (@favour_8583fe284b383faf87).</description>
    <link>https://dev.to/favour_8583fe284b383faf87</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4070936%2Fa2c3e234-a3db-4f0f-a81f-e2f588dd7eb6.png</url>
      <title>DEV Community: Moses Favour</title>
      <link>https://dev.to/favour_8583fe284b383faf87</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/favour_8583fe284b383faf87"/>
    <language>en</language>
    <item>
      <title>JCARS LOGISTICS DATA ANALYSIS WITH POWER BI</title>
      <dc:creator>Moses Favour</dc:creator>
      <pubDate>Thu, 01 Oct 2026 03:55:12 +0000</pubDate>
      <link>https://dev.to/favour_8583fe284b383faf87/jcars-logistics-data-analysis-with-power-bi-4km1</link>
      <guid>https://dev.to/favour_8583fe284b383faf87/jcars-logistics-data-analysis-with-power-bi-4km1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Jcars is a dynamic automotive retail and distribution company operating across Kenya. Catering to a diverse clientele that includes individual retail buyers, corporate, government entities, and NGOs, the company manages a complex supply chain of vehicle procurement, logistics, and sales. With branches spanning from the bustling hubs of Nairobi and Mombasa to regional yards in Kisumu and Eldoret, Jcars deals in vehicles ranging from everyday sedans and SUVs to heavy-duty commercial trucks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Data Quality Challenge
&lt;/h2&gt;

&lt;p&gt;When we first load the raw Jcars_data.csv file into Power BI, it became immediately apparent that we were dealing with a classic "real-world" dataset. We need to clean up the data before we can make any sense of it.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The primary data quality issues included:
&lt;/h2&gt;

&lt;p&gt;Date Anomalies: A chaotic mix of standard text dates ("Aug 29, 2025"), regional formats (30/08/2025 vs 03/20/2026), Excel serial numbers (45671), and outright impossible dates (April 31 2026, 2026-13-04).&lt;br&gt;
Textual Inconsistencies: Car makes and models were plagued by typos and casing issues ("Toyta", "TOYOTA", "Toyota Kenya"). Colors were heavily abbreviated ("Gre", "Bla", "Whi").&lt;br&gt;
Financial Fragmentation: Prices and revenues were recorded in multiple currencies (KES, USD, EUR, ZAR) and mixed notations ("KSh 8,136,000", "9.14M", "$ 46,038.46").&lt;br&gt;
Missing and Invalid Data: Blank Order IDs, negative discounts, and instances where the Delivery Date preceded the Order Date.&lt;br&gt;
To build a reliable Star Schema and accurate DAX measures, we could not simply "clean" the data. I tackled this through m code&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Date Inconsistencies
&lt;/h2&gt;

&lt;p&gt;Dates are the backbone of any Time Intelligence analysis. Because our dataset contained mixed regional formats, and typos, relying on Power BI’s automatic date detection was impossible. We had to build a custom parser.&lt;br&gt;
&lt;strong&gt;The Strategy:&lt;/strong&gt;&lt;br&gt;
We created a custom M function that evaluates the data type of the cell. IIf it’s text, it attempts to parse it using UK format (DD/MM/YYYY) first, falling back to US format (MM/DD/YYYY).We then added logic to catch transposition typos (like 2026-13-04) and normalize text (like changing "Sept" to "Sep"). Impossible dates (like April 31) are safely converted to null so they don't break the model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight q"&gt;&lt;code&gt;&lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="c1"&gt; 
    // 1. Convert to text and trim spaces to prevent type errors&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.From&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;    // 2. Check if the text is purely a number (Excel Serial Date)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Number.From&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;otherwise&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;    // 3. If it's a number, convert Excel serial to Date (Base date: Dec 30, 1899)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;SerialDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Date.From&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1899&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Number.From&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;    // 4. FIX TYPO: Catch "YYYY-DD-MM" transpositions (e.g., "2026-13-04" -&amp;gt; "2026-04-13")&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;FixedTypo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Middle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Middle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;let&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Part1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Middle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Part2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Middle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Part3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Middle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number.FromText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Part2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number.FromText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Part3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;Part1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Part3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Part2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CleanText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;    // 5. NORMALIZE: Change "Sept" to "Sep" to ensure the date parser accepts it&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;NormalizedText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FixedTypo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FixedTypo&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Sept"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Sep"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;    // 6. Parse the text: Try UK format first, then US format&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;TextDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NormalizedText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Date.FromText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NormalizedText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Culture&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en-GB"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;otherwise&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Date.FromText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NormalizedText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Culture&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en-US"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;otherwise&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;
&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="c1"&gt; 
    // 7. Return the valid date, or null if it's truly invalid&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SerialDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TextDate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Standardizing Text and Categorical Data
&lt;/h2&gt;

&lt;p&gt;In a Star Schema, dimension tables rely on exact text matches. If a car is listed as "Toyta" in one row and "Toyota" in another, Power Query will create two separate dimension rows, breaking our analytics.&lt;br&gt;
&lt;strong&gt;The Strategy:&lt;/strong&gt;&lt;br&gt;
We standardize the text leaving only one instance and replacing all other values with the correct instance. &lt;/p&gt;
&lt;h2&gt;
  
  
  3. Unifying Financial Metrics (Prices and Currencies)
&lt;/h2&gt;

&lt;p&gt;Calculating total revenue is impossible if one row is in Kenyan Shillings (KES), another in US Dollars (USD), and another is written as "9.14M".&lt;br&gt;
The Strategy:&lt;br&gt;
We created a two-step process. First, we extracted the raw numeric value by stripping out currency symbols, commas, and text suffixes like "M" (millions). Second, we identified the currency prefix and applied an exchange rate to convert everything into a single base currency (KES).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight q"&gt;&lt;code&gt;&lt;span class="cm"&gt;// Step 1: Extract Raw Numeric Value&lt;/span&gt;
&lt;span class="n"&gt;let&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;RawText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.From&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Selling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="c1"&gt;    // Remove currency symbols and spaces&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RawText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"KSh"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"KES"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"$"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"USD"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"EUR"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"ZAR"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;    // Handle "M" suffix for millions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.EndsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"M"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;Number.FromText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"M"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number.FromText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanedText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;otherwise&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;
&lt;span class="ow"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;

&lt;span class="cm"&gt;// Step 2: Convert to Base Currency (KES)&lt;/span&gt;
&lt;span class="n"&gt;let&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;RawValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ExtractedNumericValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CurrencyPrefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.From&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Selling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="c1"&gt; // Simplified logic for example&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ExchangeRates&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;USD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EUR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;140&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZAR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="c1"&gt; // Example static rates&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ConvertedValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.From&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Selling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.From&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Selling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RawValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ExchangeRates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;USD&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.From&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Selling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"EUR"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RawValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ExchangeRates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;EUR&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Text.Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text.From&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Selling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"ZAR"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RawValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ExchangeRates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ZAR&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RawValue&lt;/span&gt;&lt;span class="c1"&gt; // Assume KES if no prefix&lt;/span&gt;
&lt;span class="ow"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ConvertedValue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Handling Missing and Invalid Data
&lt;/h2&gt;

&lt;p&gt;A common mistake in data cleaning is deleting rows with missing Order IDs or negative discounts to make the dataset "look" clean. However, deleting rows artificially deflates revenue and hides operational flaws.&lt;br&gt;
&lt;strong&gt;The Strategy:&lt;/strong&gt;&lt;br&gt;
Instead of deleting bad data, we preserved the financial transactions but flagged the metadata errors. For missing Order IDs, we generated a unique surrogate key (SalesKey) using an Index Column to ensure every row remained technically unique. For dates where the Order Date occurred after the Delivery Date, we didn't delete the row; instead, we created a boolean flag column. This allows management to see the revenue, but filter out the bad data when calculating precise operational KPIs like "Average Delivery Time."&lt;/p&gt;

&lt;h2&gt;
  
  
  Modelling Jcar Data
&lt;/h2&gt;

&lt;p&gt;Once the data was clean, we now turn it into a Star Schema. This optimizes the PowerBI for maximum compression and query speed.&lt;br&gt;
&lt;strong&gt;The Fact Table (Jcar_merge_facts)&lt;/strong&gt;: We established the grain of the model at the individual transaction level. The Fact table was stripped of all descriptive text and populated strictly with Foreign Keys linking to the dimension tables and numeric metrics (Units Sold, Unit Cost, Discount, Revenue, Logistics Cost).&lt;br&gt;
The Dimension Tables: We turned descriptive context into highly optimized dimension tables by removing duplicates and creating unique IDs as PK to be linked as FK in the Facts table&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dim_Vehicle&lt;/strong&gt;: Granular vehicle specifications (Make, Model, Year, Fuel, Transmission, Color).&lt;br&gt;
&lt;strong&gt;Dim_CusLocation&lt;/strong&gt;: Gives the customer location (Region → County → City).&lt;br&gt;
&lt;strong&gt;DimBranch, DimSalesRep, DimCustomer, DimPayment&lt;/strong&gt;: These give the operational and demographic contexts of the business helping determine key metrics that are important in gauging the performance of different facets in Jcar data in isolation and as a combination.&lt;/p&gt;

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

&lt;p&gt;The primary keys in the various dimensions tables were linked were linked through merging. After cleaning the facts table I duplicated it such that the table that I merged the dimensions into was delinked from the facts table I had used to reference when creating the dimensions table. This is because merging to the file you referenced from will throw can error as you cannot merge a file you have referenced from in BI.&lt;br&gt;
For all the dimensions table apart from &lt;code&gt;Dim_Customer&lt;/code&gt; I used left outer join linking all matching columns facts table with the respective dimensions table while ensuring the keys &lt;code&gt;FK:PK&lt;/code&gt; are also matching. I then deleted the matching columns from the facts table as it is now represented by the foreign key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cardinality and Direction
&lt;/h2&gt;

&lt;p&gt;We configured all relationships as &lt;strong&gt;One-to-Many (1:*) with Single-Direction filter flow (from Dimension to Fact)&lt;/strong&gt;. This prevents ambiguous filter paths and ensures predictable DAX behavior. This is apart from the &lt;strong&gt;Dim_Customers which has a relationship of 1:1&lt;/strong&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Business Intelligence Logic
&lt;/h2&gt;

&lt;p&gt;This is the comprehensive summary of the Jcars business logic, structured around the logical business analysis. This framework bridges the gap between raw data and strategic decision-making, demonstrating how specific analytical work drives actionable insights and recommendations. We use DAX calculations to show the metrics of various financial statements and use our expertise to recommend actionable measures for the business.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Total Revenue:&lt;br&gt;
&lt;code&gt;Total Revenue = SUM(FactSales[Revenue Recorded])&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Total Gross Profit:&lt;br&gt;
&lt;code&gt;Total Gross Profit = SUMX(FactSales, FactSales[Units Sold] * (FactSales[Unit Selling Price] - FactSales[Unit Cost]))&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gross Profit Margin:&lt;br&gt;
&lt;code&gt;Gross Profit Margin = DIVIDE([Total Gross Profit], [Total Revenue], 0)&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Total Goods Sold:&lt;br&gt;
&lt;code&gt;Total Units Sold = SUM(FactSales[Units Sold])&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dashboard
&lt;/h2&gt;

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

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

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

&lt;h2&gt;
  
  
  Findings, Insights and Recommendations
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. Key Findings and Metrics
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Vehicle Performance (Make and Model)&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;highest revenue by Make is Toyota&lt;/strong&gt;. It stands out as the unparalleled market leader, generating approximately 0.65bn to 0.7bn Ksh which is &lt;strong&gt;roughly 44% - 47% of the total revenue.&lt;/strong&gt; It also generates the &lt;strong&gt;highest absolute Gross Profit.&lt;/strong&gt;&lt;br&gt;
Similarly the highest return by car model is the Toyota Harrier, proving to be the best selling model with 34 units sold, followed closely by the Toyota Fit 30 units and Toyota Prado TX 29 units.&lt;br&gt;
&lt;strong&gt;However there happens to be a high margin anomaly&lt;/strong&gt;. While Toyota leads in volume and revenue, the Total Revenue and Total Gross Profit by Car Make chart reveals that Volkswagen and BMW have disproportionately high gross profit margins relative to their revenue. Purporting quite a high profit margin per unit sold.hhhmmm&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Lead Source Performance&lt;/strong&gt;&lt;br&gt;
Our highest Revenue &lt;strong&gt;Lead Source comes Instagram&lt;/strong&gt;. Performing in the generation of &lt;strong&gt;271.03M (18.26%)&lt;/strong&gt; of total revenue.&lt;br&gt;
Social Media has dominated bar none with Facebook as our second highest at 230.57M (15.54%). Combined, Instagram and Facebook drive 33.8% of all company revenue.&lt;br&gt;
Other Channels: Website 11.78%, Referrals (11.64%), and Phone Calls 11.63% perform relatively evenly, while Corporate Tenders contribute the least at 9.41%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Customer &amp;amp; Payment Analysis&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;top three revenue drivers&lt;/strong&gt; Dealers (23.13%), Government (22.70%), and NGOs (20.22%). Individual  customers contribute the least at 15.11% 224.3M.&lt;br&gt;
Payment collection issues: The Total Revenue by Payment Method and Payment Status chart highlights a major operational risk. Across all major payment methods (M-Pesa, Cash, Cheque, Bank Transfer), there are massive blocks of "Pending" (purple) and "Partially Paid" (orange) statuses. An example is M-Pesa and Cash both have roughly 20-25% of their revenue stuck in pending or partially paid states.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Regional &amp;amp; Branch Performance&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Top Branches: Kakamega is the highest performing branch (255M), followed by Thika 247M  and Nakuru 212M .&lt;/strong&gt;&lt;br&gt;
Underperforming Branch: &lt;strong&gt;Nairobi is the lowest-performing branch&lt;/strong&gt;, generating only 78.53M, which is roughly 30% of Kakamega's performance despite being in the capital city. This may need some investigation.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Strategic Insights
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A. The "Toyota Reliance" Risk:&lt;/strong&gt; Relying on a single make for nearly half of revenue exposes JCars to supply chain shocks or market saturation. Look to diversify into other brands that may spread the risk even though the toyota seems to be "darling"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Cash Flow impeding dilemma: The high volume of "Pending" and "Partially Paid" transactions indicates that while sales teams are good at closing deals, the collections/finance team is struggling to finalize payments. This artificially inflates revenue figures while starving the company of actual working capital.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Marketing ROI speaks for itself&lt;/strong&gt;. Ancient methods such as walk-ins, phone calls and expensive B2B efforts like the Corporate Tenders are underperforming compared to social media marketing Ig and Fb, which bring in majority of the revenue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D. The Nairobi anomaly&lt;/strong&gt; in it's severe underperformance suggests either intense local competition, poor branch management, or a mismatch in inventory eg stocking cars that don't appeal to the Nairobi demographic, or part of the cars that are unaccounted for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommendations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Procurement and inventory segment priorities&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Maintain Toyota Stock and continue prioritizing the procurement of Toyota Harriers, Prado TXs, and Fits, as they are the proven volume and revenue drivers.&lt;/li&gt;
&lt;li&gt;Prioritize increasing the inventory of Volkswagen and BMW, to capitalize on high margin brands the dashboards show they yield exceptionally high gross profit margins. Selling just a few more units of these could significantly boost the company's revenue without needing massive volume.&lt;/li&gt;
&lt;li&gt;Diversify: Slowly introduce more Mazda and Mercedes-Benz inventory to capture the mid-to-high-end market that isn't buying Toyota.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Marketing &amp;amp; Sales Strategy&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Shift marketing budget away from low-performing channels and heavily invest in Instagram and Facebook. Since they generate 34% of revenue, JCars should implement targeted ad campaigns specifically for the Toyota Harrier and Prado TX on these platforms.&lt;/li&gt;
&lt;li&gt;Incentivize referrals as they generate 11.64% of revenue . Implementing a formal &lt;strong&gt;Customer Referral Bonus&lt;/strong&gt; program could easily push this channel into the top 3.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Operational &amp;amp; Financial Improvements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;I recommend having a collection taskforce as a course of action. Management must immediately address the "Pending" and "Partially Paid" backlog. Implement strict SLAs (Service Level Agreements) for sales reps to follow up on pending payments within 48 hours of delivery. Consider tying sales commissions to collected revenue rather than booked revenue.&lt;/li&gt;
&lt;li&gt;Audit Nairobi branch: Conduct an immediate operational audit of the Nairobi branch. Compare its inventory mix, staff performance, and lead response times against the Kakamega branch to identify why the capital city branch is lagging so severely.&lt;/li&gt;
&lt;li&gt;Boost Individual Retail: Since Individual customers make up the smallest segment (15.11%), JCars should consider creating Retail-Only weekend promotions or flexible micro-financing options to attract individual buyers who may not have the bulk capital of Dealers or NGOs.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This project demonstrates the critical journey from raw, unstructured data to strategic business intelligence for Jcars. By rigorously cleaning the dataset and creating a robust star schema, we transformed unreliable records into a high-performance analysis. Jcars is now equipped to optimize profit margins, streamline its supply chain, and drive sustainable growth in a competitive automotive market in the Kenya market.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/waweroh/jcar-sales-modeling-analytics" rel="noopener noreferrer"&gt;https://github.com/waweroh/jcar-sales-modeling-analytics&lt;/a&gt;&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>business</category>
      <category>data</category>
    </item>
    <item>
      <title>Data Modelling, Relationships &amp; Joins</title>
      <dc:creator>Moses Favour</dc:creator>
      <pubDate>Fri, 25 Sep 2026 09:34:36 +0000</pubDate>
      <link>https://dev.to/favour_8583fe284b383faf87/data-modelling-relationships-joins-34d6</link>
      <guid>https://dev.to/favour_8583fe284b383faf87/data-modelling-relationships-joins-34d6</guid>
      <description>&lt;h2&gt;
  
  
  Data Modelling in Power BI
&lt;/h2&gt;

&lt;p&gt;In data analytics and business intelligence the success of a power BI solution lies in it's data model. Exploring data modelling principles, relationships management and join operations equips you with the knowledge to design a robust data model. A well-architected data model &lt;strong&gt;ensures accuracy in your analytics&lt;/strong&gt; as well as &lt;strong&gt;simplicity in your DAX calculations&lt;/strong&gt;. &lt;strong&gt;Data modelling&lt;/strong&gt; is the process of organizing, defining and designing tables, how they establish relationships with other tables and rules that govern data interactions. It becomes the blue print through which data is stored, filtered and queried to answer business questions and give insight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Components of Data Modelling:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tables&lt;/strong&gt;: Containers for your data (facts and dimensions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relationships&lt;/strong&gt;: Connections between tables (one-to-many, many-to-one). How many rows in one table can link to rows in another.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keys&lt;/strong&gt;: Unique identifiers (Primary Keys and Foreign Keys)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cardinality&lt;/strong&gt;: The nature of relationships (1:1, 1:M, M:M).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter Direction&lt;/strong&gt;: How filters flow between tables (single or bi-directional)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Flat table
&lt;/h2&gt;

&lt;p&gt;It represents the simplest form of data modelling where all data elements exist within a single table structure and with no relationships with other tables. The table is a massive data set which contains data redundancy, mixed granularity example the data contains customer information together with  product store data. It's primary &lt;strong&gt;advantage&lt;/strong&gt; is that its simple with no complex logic or relationships to understand. The &lt;strong&gt;disadvantage&lt;/strong&gt; far out way advantages. Flat tables cannot provide any business intelligence solutions as the data is very redundant. If a customer like "Jack" has made fifty purchases, his name, email address, segment classification, and geographical information are duplicated fifty times across the table. This redundancy wastes memory and storage space, leading to bloated file sizes that can be five to ten times larger than necessary. When you need to update customer information, you must modify every single row where that customer appears, creating opportunities for data inconsistency and requiring expensive update operations. This leads to poor performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Star Schema
&lt;/h2&gt;

&lt;p&gt;The star schema represents the industry-standard approach for dimensional modelling in business intelligence and is the recommended design pattern for Power BI solutions. This architecture consists of a central fact table surrounded by multiple dimension tables, creating a structure that resembles a star when visualized in the model diagram. &lt;strong&gt;The fact table **sits at the center and contains the measurable, quantitative data about business processes, while the **dimension tables&lt;/strong&gt; radiate outward and contain the descriptive attributes that provide context for analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of a star schema approach
&lt;/h3&gt;

&lt;p&gt;In a retail sales scenario, the &lt;strong&gt;fact table **would be named FactSales and would contain one row for each individual sales transaction. Each row would include foreign key references to dimension tables, such as DateKey, CustomerKey, ProductKey, and StoreKey, along with numeric measurements like SalesAmount, Quantity, Discount, and Profit. **The dimension tables&lt;/strong&gt;, such as DimDate, DimCustomer, DimProduct, and DimStore, contain the descriptive attributes. DimDate might include columns like FullDate, Year, Quarter, Month, Day, DayOfWeek, and IsHoliday. DimCustomer would contain CustomerName, Email, Segment, Region, and City. DimProduct would include ProductName, Category, Subcategory, and Supplier. DimStore would contain StoreName, Address, City, State, and Region.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Separating the repetitive foreign keys and having relatively small dimension tables improves query performance ie faster than flat tables.&lt;/li&gt;
&lt;li&gt;DAX calculations become remarkably simpler because relationships enable automatic filter propagation.&lt;/li&gt;
&lt;li&gt;Data redundancy is minimized because each dimension attribute is stored only once. Customer information exists in a single row in DimCustomer and is referenced by the CustomerKey foreign key in every related sales transaction.&lt;/li&gt;
&lt;li&gt;Scalability is excellent because the fact table can grow to billions of rows while dimension tables remain relatively small and stable.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Snowflake Schema Approach.
&lt;/h2&gt;

&lt;p&gt;The snowflake schema represents a normalized variation of the star schema where dimension tables are further broken down into sub-dimensions, creating multiple levels of related tables that resemble a snowflake pattern when visualized. &lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Has reduced storage requirements through additional normalization. Category names are stored only once in DimCategory rather than being repeated for every subcategory and product, and subcategory names are stored once rather than repeated for every product.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Performance degradation is the most critical issue because queries must traverse multiple relationships to reach the descriptive attributes. &lt;/li&gt;
&lt;li&gt;DAX calculations become more complex because measures must account for the additional relationship layers. Simple calculations that would be automatic in a star schema require explicit handling of filter context across multiple tables. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Relationships in Power BI
&lt;/h2&gt;

&lt;p&gt;In Power BI, a relationship is a logical connection between two tables that enables the automatic propagation of filters from one table to another, allowing data from multiple tables to be queried and analyzed together as if it were a single unified dataset.Without relationships, Power BI would have no way of knowing how to connect a customer's name in DimCustomer to their sales transactions in FactSales, or how to associate a product's category in DimProduct with its sales amounts in FactSales.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cardinalities
&lt;/h3&gt;

&lt;p&gt;Relationship cardinality describes the numerical relationship between rows in one table and rows in another table, and Power BI supports three primary cardinality types: one-to-many, one-to-one, and many-to-many. Cardinality refers to the &lt;strong&gt;uniqueness of data in a column **and is closely related to the **concept of primary and foreign keys.&lt;/strong&gt; A column with &lt;strong&gt;high cardinality&lt;/strong&gt; has many unique values relative to the total number of rows, such as a &lt;strong&gt;transaction ID column&lt;/strong&gt; where every row has a different value. A column with &lt;strong&gt;low cardinality&lt;/strong&gt; has few unique values relative to the total number of rows, such as a &lt;strong&gt;gender column with only two or three distinct values.&lt;/strong&gt; In relationships, the "&lt;strong&gt;one" side typically has high cardinality&lt;/strong&gt; (one unique value per row), &lt;strong&gt;while the "many" side has low cardinality&lt;/strong&gt; (many rows sharing the same foreign key value).&lt;/p&gt;

&lt;h3&gt;
  
  
  One-to-Many relationships
&lt;/h3&gt;

&lt;p&gt;A single row in Table A can match multiple rows in Table B. &lt;strong&gt;Example&lt;/strong&gt;: &lt;strong&gt;A Customer table linked to an Orders table (one customer can place many orders).This is the most used relationship.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  One-to-One relationship
&lt;/h3&gt;

&lt;p&gt;Each row in Table A matches exactly one row in Table B. &lt;strong&gt;Example:&lt;/strong&gt; &lt;strong&gt;A User table linked to a User_Passport table (one person has one passport).&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Many-to-Many relationship
&lt;/h3&gt;

&lt;p&gt;A many-to-many relationship exists when rows in the first table can be associated with multiple rows in the second table, and rows in the second table can also be associated with multiple rows in the first table. &lt;strong&gt;Example:&lt;/strong&gt; &lt;strong&gt;A Student table linked to a Classes table (a student takes many classes; a class has many students).&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter Direction
&lt;/h2&gt;

&lt;p&gt;Filter direction determines how filters applied to one table flow through relationships to affect other related tables in your data model. Understanding filter propagation is essential for creating accurate reports and avoiding common pitfalls that can lead to incorrect results or performance problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-direction filtering
&lt;/h3&gt;

&lt;p&gt;Single-direction filtering, also known as one-way filtering, is the default and recommended filter direction for most relationships in Power BI. &lt;strong&gt;In a single-direction relationship, filters flow from the "one" side of the relationship (typically a dimension table) to the "many" side (typically a fact table),&lt;/strong&gt; but not in the reverse direction. This means that when you select a value in a dimension table, such as clicking on "Electronics" in a DimProduct[Category] slicer, that filter automatically propagates to the FactSales table, showing only sales transactions for products in the Electronics category. However, filters do not flow from FactSales back to DimProduct, which means that selecting a specific sales amount range in a fact table measure would not filter the products shown in a dimension table visual.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bidirectional filtering
&lt;/h3&gt;

&lt;p&gt;Bidirectional filtering, also known as both-direction filtering or cross-filtering, allows filters to flow in both directions across a relationship, from the "one" side to the "many" side and from the "many" side back to the "one" side. When bidirectional filtering is enabled, selecting a value in either table affects the other table, creating a two-way filter propagation. Bidirectional filtering can be useful in specific scenarios, such as when you have a many-to-many relationship implemented with a bridge table, and you need filters to flow from both dimension tables through the bridge table to the fact table. &lt;/p&gt;

&lt;h2&gt;
  
  
  Joins in Power Query
&lt;/h2&gt;

&lt;p&gt;A join is an operation that combines rows from two tables based on a related column between them, creating a single unified table that contains columns from both source tables. Joins are performed using the Merge Queries feature in Power Query Editor, which allows you to specify which columns to match between tables and what type of join to perform. &lt;/p&gt;

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

&lt;h3&gt;
  
  
  Left Outer Join
&lt;/h3&gt;

&lt;p&gt;A left outer join, often simply called a left join, returns all rows from the left table (the first table you select in the merge operation) and only the matching rows from the right table (the second table). If a row in the left table has no matching row in the right table, the columns from the right table will contain null values for that row, but the row from the left table is still included in the result&lt;/p&gt;

&lt;h3&gt;
  
  
  Right Outer Join
&lt;/h3&gt;

&lt;p&gt;A right outer join is the mirror image of a left outer join, returning all rows from the right table (the second table) and only the matching rows from the left table (the first table). If a row in the right table has no matching row in the left table, the columns from the left table will contain null values, but the row from the right table is still included.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full Outer Join
&lt;/h3&gt;

&lt;p&gt;A full outer join, also known as a full join or outer join, returns all rows from both tables, matching rows where possible and filling in null values where no match exists. This join type preserves every row from both the left table and the right table, regardless of whether matching rows exist in the opposite table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inner Join
&lt;/h3&gt;

&lt;p&gt;An inner join returns only the rows that have matching values in both tables, excluding any rows that do not have a match in the opposite table. This is the most restrictive join type because it filters out any records that cannot be matched between the two tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Left Anti Join
&lt;/h3&gt;

&lt;p&gt;A left anti join, also known as a left semi join or excluding join, returns only the rows from the left table that do not have matching rows in the right table. This join type is essentially the opposite of an inner join from the perspective of the left table, returning only the unmatched records.&lt;br&gt;
In the Customers and Orders example, a left anti join would return only customers who have never placed an order. Any customer who appears in the Orders table would be excluded from the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Query Joins vs Power BI Relationships: Understanding the Distinction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A Power Query merge&lt;/strong&gt; operation physically combines columns and data from two or more tables into a single unified table during the data transformation phase, which occurs before the data is loaded into the Power BI data model.&lt;br&gt;
In contrast, &lt;strong&gt;creating a relationship in the Power BI data model&lt;/strong&gt; does not physically combine tables or duplicate data. Instead, a relationship creates a logical connection between two separate tables that remain distinct entities in the model. The relationship enables filter propagation and allows DAX calculations to access data from related tables without physically merging them. The tables stay separate in memory, and the relationship is evaluated dynamically at query time when users interact with reports or when DAX measures are calculated.&lt;br&gt;
&lt;strong&gt;When deciding whether to use a merge or a relationship, the guiding principle should be to use relationships whenever possible and reserve merges for specific scenarios where denormalization is necessary&lt;/strong&gt;. Keeping fact and dimension tables separate through relationships rather than merging them into flat tables provides numerous advantages. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, the star schema with one-to-many, single-direction relationships represents the optimal design pattern for Power BI data models. It delivers superior performance, simpler DAX, better scalability, easier maintenance, and more intuitive report development compared to flat tables or snowflake schemas. While it requires more upfront effort to design and implement than simply importing flat tables, the long-term benefits in terms of performance, maintainability, and user satisfaction make it the clear choice for any serious business intelligence project. &lt;/p&gt;

</description>
      <category>data</category>
      <category>datamodelling</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Getting Started with Excel for Data Analytics: From Basics to Data Cleaning.</title>
      <dc:creator>Moses Favour</dc:creator>
      <pubDate>Wed, 02 Sep 2026 19:21:32 +0000</pubDate>
      <link>https://dev.to/favour_8583fe284b383faf87/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-5bec</link>
      <guid>https://dev.to/favour_8583fe284b383faf87/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-5bec</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Microsoft Excel is a spreadsheet program used to organize, calculate, analyze, and visualize data in rows and columns. It is organized in worksheets that are contained in the workbook - the file.&lt;br&gt;
Data analysis is the process of cleaning, organizing and examining raw data to find useful patterns the support business decisions.&lt;br&gt;
Data is often received in it rawest form which is disorganized and in order to make business sense of it, the data must be cleaned and organized. &lt;strong&gt;So how do we clean raw data and make business sense out of it.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Filtering
&lt;/h3&gt;

&lt;p&gt;Filtering is temporarily conceals rows that do not fit your rules. It displays a smaller, relevant subset of data while leaving the original row order untouched.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using filtering to clean data&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto fit the column width to see column data properly. &lt;code&gt;Home tab Cell&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select the row with all the headers and select filter. This will enable us to remove unwanted data fields our columns.&lt;/li&gt;
&lt;li&gt;When cleaning data for non-unique input values we need columns to have only one instance of a text field. We do this by deleting all other text fields until we remain with unique ones. An example would be having HR and human resource both as input fields instead of one instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F73u4fhrsyly0yqzfcxm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F73u4fhrsyly0yqzfcxm1.png" alt="Data filtering with excel" width="800" height="402"&gt;&lt;/a&gt;&lt;br&gt;
In this column we have only one instance of every department. In such columns we often use data validation to ensure that inputs are strictly of a specific type. Example Male or female, or a specific department.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using filtering for analysis&lt;/strong&gt; &lt;br&gt;
In excel we can filter by certain types of data namely &lt;strong&gt;text, numbers and date&lt;/strong&gt;. This means we can conceal all other data and get only the data that fits our criteria&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjgyhicuzxddx6rrxqs0p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjgyhicuzxddx6rrxqs0p.png" alt="text filter in excel" width="799" height="377"&gt;&lt;/a&gt;&lt;br&gt;
Above is &lt;strong&gt;text filter&lt;/strong&gt;. We are filtering last names column for names beginning with 'mbo'&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp5bd0kopxo6g6h6tsx4n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp5bd0kopxo6g6h6tsx4n.png" alt="filtering numbers in excel" width="799" height="413"&gt;&lt;/a&gt;&lt;br&gt;
We have various options for &lt;strong&gt;number filters&lt;/strong&gt;. Example we can filter for salaries that are greater than 50,000 using the option provided.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F94ktwsfdx6o8oehmh2qm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F94ktwsfdx6o8oehmh2qm.png" alt="Date filtering with excel" width="800" height="413"&gt;&lt;/a&gt;&lt;br&gt;
This is &lt;strong&gt;date filter&lt;/strong&gt;. We use it to get specific time lines and time ranges.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Sorting
&lt;/h3&gt;

&lt;p&gt;Sorting changes the physical position and order of rows (such as &lt;strong&gt;A to Z, Z to A, smallest to largest, or by cell color&lt;/strong&gt;). All data remains visible on the sheet unlike filtering that hides data giving only what was filtered. It is found in &lt;code&gt;home -&amp;gt; editing&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multilevel Sorting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feh1d51hj3rzdnyimg9jk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feh1d51hj3rzdnyimg9jk.png" alt="Multi level sorting" width="800" height="393"&gt;&lt;/a&gt;&lt;br&gt;
Here we are sorting our data by the columns department, gender and age. This rearranges the entire worksheet to fit this parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Conditional Formatting.
&lt;/h3&gt;

&lt;p&gt;Conditional formatting in Excel is a tool that changes the look of cells automatically based on their content. It lets you use **colors, icons, or data bars to spot trends, high values, or errors and duplicates **without looking through rows by hand&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8s7t8hvb9pi50uvkop66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8s7t8hvb9pi50uvkop66.png" alt="Conditional formatting" width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
In this instance we are using conditional formatting on the employeeID column  to highlight duplicates using a specific color, since the ID values are supposed to be unique any duplicate should be deleted&lt;br&gt;
Conditional formatting can also be used on &lt;strong&gt;&lt;em&gt;dates and time, getting values that are greater or less than, to highlight text that contains a specific text, getting top 10%.&lt;/em&gt;&lt;/strong&gt; Explore the conditional formatting options&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Data Validation
&lt;/h3&gt;

&lt;p&gt;Data validation is a feature that restricts what users can type into a cell or a range of cells to keep the data clean and accurate. Found in the &lt;code&gt;data tab --&amp;gt; data tools group&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fygnw502zmzsfof2l9p6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fygnw502zmzsfof2l9p6x.png" alt="Data validation in excel" width="799" height="413"&gt;&lt;/a&gt;&lt;br&gt;
In the above image we have validate the department column to only accept a list of departments available in the organization &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo0i17o6dmk2nuj0yr9ul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo0i17o6dmk2nuj0yr9ul.png" alt="Data validation list" width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
In this example we see that to input values into the department column we have a drop down list to select from&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The data validation criteria can also cater for &lt;strong&gt;dates, time whole numbers, lists and text length&lt;/strong&gt;. This ensures that the data being input in the cell already meets the criteria for that column or cell. The process ensures incoming data is clean.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Functions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Aggregation Function&lt;/strong&gt;&lt;br&gt;
Aggregate function calculate a single summary value such as a sum, average, or count from a list of numbers&lt;br&gt;
&lt;code&gt;Count&lt;/code&gt; - The function is used to count non-numeric cells.&lt;br&gt;
&lt;code&gt;CountA&lt;/code&gt; - counts non-blank cells in the column&lt;br&gt;
&lt;code&gt;CountBlank&lt;/code&gt; - Counts blank cells in a column &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conditional Aggregations&lt;/strong&gt;&lt;br&gt;
A conditional aggregate function in Excel summarizes a set of data (like adding numbers or counting rows) only for the cells that meet a specific rule or condition.&lt;br&gt;
Examples are &lt;code&gt;COUNTIFS&lt;/code&gt;, &lt;code&gt;SUMIFS&lt;/code&gt;, &lt;code&gt;COUNTIF&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvhqw5f8jxo4sm7ijwl1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvhqw5f8jxo4sm7ijwl1g.png" alt="Sumifs function in excel" width="799" height="413"&gt;&lt;/a&gt;&lt;br&gt;
In the above image we use &lt;code&gt;SUMIFS&lt;/code&gt; to &lt;strong&gt;calculate the sum of salary&lt;/strong&gt;(range) if the &lt;strong&gt;gender is female&lt;/strong&gt;(range and text) and the department is Finance (range and text). Using the syntax provided.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Statistical Functions&lt;/strong&gt;&lt;br&gt;
Statistical Functions to analyze, summarize, and interpret data. They include &lt;code&gt;mean, median and mode&lt;/code&gt;.&lt;br&gt;
Note that the median and the average should not have a big difference if the data is consistent and has no outliers&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fga6c4avnk3uh9guhql5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fga6c4avnk3uh9guhql5d.png" alt="Median" width="800" height="428"&gt;&lt;/a&gt;&lt;br&gt;
Here we find the median for out salary column&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Date and time functions&lt;/strong&gt;&lt;br&gt;
Excel date and time functions work like a hidden digital calendar and clock that let you track, display, and calculate days and hours with ease.&lt;br&gt;
&lt;code&gt;=YEAR(A1) =MONTH(A1) =DAY(A1)&lt;/code&gt; This are some of the date and time functions &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text Functions&lt;/strong&gt;&lt;br&gt;
This are functions that format text for a certain expected outcome. Example: &lt;code&gt;CONCAT&lt;/code&gt;(adding two strings together), &lt;code&gt;TRIM&lt;/code&gt;, &lt;code&gt;PROPER&lt;/code&gt;(first letter capitalization)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6m7lb7vdv0leqgjapp4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6m7lb7vdv0leqgjapp4i.png" alt="Text function CONCAT and LOWER" width="800" height="396"&gt;&lt;/a&gt;&lt;br&gt;
In this example we use the text functions &lt;code&gt;CONCAT and LOWER&lt;/code&gt; to join the &lt;strong&gt;first and last name and form an email field from that text&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion.&lt;/strong&gt;&lt;br&gt;
This article explains how you can clean data and analyze data using excel using tools like data validation, functions, filters and sorts. It helps capture the power of excel in your data analysis journey.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>datacleaning</category>
      <category>excel</category>
    </item>
    <item>
      <title>Understanding the Git Workflow: Working Directory, Staging, Commit and Push</title>
      <dc:creator>Moses Favour</dc:creator>
      <pubDate>Sat, 22 Aug 2026 09:52:30 +0000</pubDate>
      <link>https://dev.to/favour_8583fe284b383faf87/understanding-the-git-workflow-working-directory-staging-commit-and-push-5894</link>
      <guid>https://dev.to/favour_8583fe284b383faf87/understanding-the-git-workflow-working-directory-staging-commit-and-push-5894</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Git is a version control system that tracks changes in code. When writing code we need to save every significant change or feature that does a certain function as a commit that can be reverted to if we ever need that instance of the code. This helps programmers to traverse code since nothing is ever lost in the product life cycle of the project. It also helps in debugging since we have a copy of the previous working state. So how do we start out with git you ask.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install git
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://git-scm.com/install/" rel="noopener noreferrer"&gt;git&lt;/a&gt; for your specific operating system. After installing git you will note that the file comes with git bash which is a command line terminal that is used to run commands or instruct the version control git.&lt;/li&gt;
&lt;li&gt;To ensure that git has been installed open git bash and run the command &lt;code&gt;git --version&lt;/code&gt; which will return the version of git installed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Download Visual Studio Code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://code.visualstudio.com/download?_exp_download=d53503e735" rel="noopener noreferrer"&gt;VS code&lt;/a&gt; a text editor for writing code.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Create a github account
&lt;/h2&gt;

&lt;p&gt;GitHub is a cloud-based platform used by developers to store,  track, and collaborate on software code. It operates as a hosting service for git, an open-source version control system that tracks changes made to files.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Head over to &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;github&lt;/a&gt; and create and account&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating a directory tracked by git
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;On git bash run &lt;code&gt;mkdir &amp;lt;filename&amp;gt;&lt;/code&gt;. This will create a folder ie the project that will contain your files of code. &lt;/li&gt;
&lt;li&gt;Enter the folder through &lt;code&gt;cd &amp;lt;filename&amp;gt;&lt;/code&gt; and create a file README.md file which explains what this project does &lt;code&gt;touch README.md&lt;/code&gt;. Run the command &lt;code&gt;ls&lt;/code&gt; to list files in the directory&lt;/li&gt;
&lt;li&gt;Open the vs code from terminal by running &lt;code&gt;code .&lt;/code&gt; and edit the README.md file. Now the file is ready to be tracked by git on github&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Staging, committing and pushing
&lt;/h2&gt;

&lt;p&gt;We now need to initialize the directory making sure that git is now tracking the file. Running the commands &lt;code&gt;ls-la&lt;/code&gt; will confirm that git has been initialized in the repository. There are two ways of doing this either via the &lt;strong&gt;text editor VS code or the terminal&lt;/strong&gt;. Let us go through both.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. VS code
&lt;/h3&gt;

&lt;p&gt;Make sure your VS code is connected to your github account.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the source control icon (third from top) and &lt;strong&gt;Initialize Repository&lt;/strong&gt;. This will introduce git to track the file&lt;/li&gt;
&lt;li&gt;Hover over the file and &lt;strong&gt;click the + button to add the file. This changes the file from U (untracked) to A (added)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Write the &lt;strong&gt;commit message in the input box above&lt;/strong&gt; describing what you are committing eg add README.md file.&lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;commit button press the drop down arrow **for more options and **press commit and sync&lt;/strong&gt;. This will now stage your repository to be pushed to github.&lt;/li&gt;
&lt;li&gt;Click on publish branch and set the repository to either public or private.&lt;/li&gt;
&lt;li&gt;Go to your github and refresh to see your newly pushed repository that is now tracked by git.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Using the terminal
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open your terminal ie. gitbash  and go to your folder.&lt;/li&gt;
&lt;li&gt;Initialize Git using &lt;code&gt;git init&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add your files using &lt;code&gt;git add .&lt;/code&gt; to track them.&lt;/li&gt;
&lt;li&gt;Commit the files using &lt;code&gt;git commit -m "first commit"&lt;/code&gt;. This should describe what we are committing and will  to save the change locally.&lt;/li&gt;
&lt;li&gt;Link your remote repository using &lt;code&gt;git remote add origin &amp;lt;your-repo-url&amp;gt;&lt;/code&gt;.Preferably use the ssh link option &lt;/li&gt;
&lt;li&gt;Push the files using &lt;code&gt;git push -u origin main&lt;/code&gt; to send your code to GitHub and publish the repository as the main branch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With that now you know how to set up a project and keep track of your changes using github.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>git</category>
      <category>github</category>
    </item>
  </channel>
</rss>
