<?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: Wendy Ochieng</title>
    <description>The latest articles on DEV Community by Wendy Ochieng (@wendy_ochieng).</description>
    <link>https://dev.to/wendy_ochieng</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%2F4071789%2F02b9fb91-782b-4a6a-b4c9-bfaa20d5a056.png</url>
      <title>DEV Community: Wendy Ochieng</title>
      <link>https://dev.to/wendy_ochieng</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wendy_ochieng"/>
    <language>en</language>
    <item>
      <title>Power BI: Data Modelling, Relationships &amp; Joins</title>
      <dc:creator>Wendy Ochieng</dc:creator>
      <pubDate>Sun, 13 Sep 2026 12:30:30 +0000</pubDate>
      <link>https://dev.to/wendy_ochieng/power-bi-data-modelling-relationships-joins-2mgl</link>
      <guid>https://dev.to/wendy_ochieng/power-bi-data-modelling-relationships-joins-2mgl</guid>
      <description>&lt;h1&gt;
  
  
  1. Data Modelling in Power BI
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;What is Data Modeling?&lt;/em&gt;&lt;br&gt;
Data Modeling is how you organize and connect your tables in Power BI so they work together properly.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Data modelling&lt;/em&gt; is the discipline of not writing everything on one page. It's deciding where each piece of information belongs so it only must be written once, and everything else just points back to it.&lt;/p&gt;

&lt;p&gt;In the Kenya Crops csv, "Kiambu" and "Potatoes" repeat on every row a Kiambu potato farmer shows up in. A well-designed model instead stores "Kiambu" once and "Potatoes" once. The harvest record in the fact table just holds a short reference (a key) back to each of them. That's the whole idea behind data modelling: separate the things that describe (farmer, county, crop i.e., who/what/where) from the things that happen (a harvest event with its yield, revenue, and cost), so each fact is stored once and reused everywhere it's needed.&lt;/p&gt;

&lt;p&gt;If the data is all scrambled up, it may create problems when trying to find specific things. In Power BI, these problems include&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Duplication&lt;/li&gt;
&lt;li&gt;Difficulty in updating&lt;/li&gt;
&lt;li&gt;Extra Large files&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can thus split a table into multiple smaller connected tables. These connections are called &lt;strong&gt;relationships&lt;/strong&gt; which will be discussed later in this article.&lt;/p&gt;

&lt;p&gt;Data modeling organizes data into a structured model by;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Organizing tables and columns&lt;/li&gt;
&lt;li&gt;Defining relationships between tables&lt;/li&gt;
&lt;li&gt;Setting cardinality and cross-filter direction&lt;/li&gt;
&lt;li&gt;Supporting accurate calculations and reporting&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Data Models
&lt;/h2&gt;

&lt;p&gt;The underlying structure that organizes and relates data tables for analysis.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. FLAT TABLE
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Definition
&lt;/h4&gt;

&lt;p&gt;A flat table is a data model in which most or all of the information required for analysis is stored in a single table. Instead of separating information into fact and dimension tables, descriptive attributes and numerical measures are stored together in the same table.&lt;/p&gt;
&lt;h4&gt;
  
  
  Structure
&lt;/h4&gt;

&lt;p&gt;Using the Kenya crops dataset, a flat table could contain fields such as:&lt;br&gt;
Crop | County | Sub-County | Year | Season | Area Harvested | Yield | Production&lt;br&gt;
Every row represents a record, with all relevant information stored together.&lt;/p&gt;
&lt;h4&gt;
  
  
  Advantages
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Simple to understand and create.&lt;/li&gt;
&lt;li&gt;No relationships between tables are required.&lt;/li&gt;
&lt;li&gt;Suitable for small datasets and simple reports.&lt;/li&gt;
&lt;li&gt;Easy to use for basic Power BI visualizations.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Disadvantages
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Information can be repeated many times.&lt;/li&gt;
&lt;li&gt;Can become large and difficult to maintain.&lt;/li&gt;
&lt;li&gt;Less suitable for complex analysis.&lt;/li&gt;
&lt;li&gt;Limited scalability as the dataset grows.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Appropriate situations
&lt;/h4&gt;

&lt;p&gt;A flat table is suitable for small datasets, simple reports, prototypes, or one-off analysis.&lt;/p&gt;
&lt;h4&gt;
  
  
  Power BI implications
&lt;/h4&gt;

&lt;p&gt;It has low modelling complexity because there are few or no relationships. However, a large flat table can contain significant repetition and become less efficient as the dataset grows.&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%2Fbpeck0hj09t84hf4unx4.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%2Fbpeck0hj09t84hf4unx4.png" alt="Flat Table" width="544" height="535"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. STAR SCHEMA
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Definition
&lt;/h4&gt;

&lt;p&gt;A mature data modeling approach with a central fact table surrounded by dimension tables, like points on a star, optimized for performance and simplicity  in reporting.&lt;/p&gt;
&lt;h4&gt;
  
  
  Structure:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Center&lt;/strong&gt;: Harvest (fact table with harvest transactions. one row per farmer's harvest, holding the numbers: Yield (Kg), Revenue (KES), Cost of Production (KES), Profit (KES))&lt;br&gt;
&lt;strong&gt;Points&lt;/strong&gt;: Farmer, Crop, County, Date (dimension tables, the who/what/where/when)&lt;br&gt;
&lt;strong&gt;Connections&lt;/strong&gt;: Each dimension connects directly to Harvest&lt;br&gt;
Key characteristic: Dimensions are denormalized (flat)&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%2Ftm8uthlvxa5kd3wzf1va.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%2Ftm8uthlvxa5kd3wzf1va.png" alt="Star Schema" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Advantages
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Easy to understand&lt;/li&gt;
&lt;li&gt;Fast performance. Queries run faster. Refreshes complete quicker.&lt;/li&gt;
&lt;li&gt;Easy to maintain&lt;/li&gt;
&lt;li&gt;User friendly.&lt;/li&gt;
&lt;li&gt;Easily scalable. Works the same for data with 1000 rows or 1 million rows&lt;/li&gt;
&lt;li&gt;Simple measures
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;Total Yield = SUM('Kenya_Crops_Dataset 5'[Yield (Kg)])&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h4&gt;
  
  
  Disadvantages
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;More complex than a flat table.&lt;/li&gt;
&lt;li&gt;Requires relationships between tables.&lt;/li&gt;
&lt;li&gt;Requires understanding of keys, relationships and data granularity.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Appropriate situations
&lt;/h4&gt;

&lt;p&gt;A star schema is particularly suitable for medium-to-large Power BI reports, business intelligence systems, and datasets requiring multiple types of analysis.&lt;/p&gt;

&lt;h4&gt;
  
  
  Power BI implications
&lt;/h4&gt;

&lt;p&gt;The star schema is generally the preferred approach for Power BI. Its clear separation between measurable data and descriptive data supports efficient filtering, grouping and calculations.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. SNOWFLAKE SCHEMA
&lt;/h3&gt;

&lt;p&gt;An extension of a star, and includes relationships between dimension tables and related sub-dimension tables. In short, Dimension tables have their own dimension tables, creating branches like a snowflake.&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%2F1jbagqh6p6pwvvmjzs6d.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%2F1jbagqh6p6pwvvmjzs6d.png" alt="Snowflake" width="543" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Structure
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Center:&lt;/strong&gt; Harvest (same fact table)&lt;br&gt;
&lt;strong&gt;Points:&lt;/strong&gt; Farmer, Crop, Date, and County but County now points on to a further table&lt;br&gt;
&lt;strong&gt;Extra point:&lt;/strong&gt; Region, connected only to County (not directly to Harvest)&lt;br&gt;
&lt;strong&gt;Connections:&lt;/strong&gt; Farmer, Crop, and Date connect directly to Harvest, exactly like the star. County also connects directly to Harvest, but County itself connects to Region one level out.&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%2Fm0zravi23i48c1wflah4.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%2Fm0zravi23i48c1wflah4.png" alt="Snowflake schema" width="799" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Advantages
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Reduces duplication.&lt;/li&gt;
&lt;li&gt;Organizes hierarchical information clearly.&lt;/li&gt;
&lt;li&gt;Can be useful when dimensions contain complex hierarchies.&lt;/li&gt;
&lt;li&gt;Can reflect a normalized database structure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Disadvantages
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Requires more tables and relationships.&lt;/li&gt;
&lt;li&gt;More difficult to understand and maintain.&lt;/li&gt;
&lt;li&gt;Creates longer filtering paths.&lt;/li&gt;
&lt;li&gt;Can increase Power BI model complexity.&lt;/li&gt;
&lt;li&gt;May be less efficient than a star schema for reporting.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Appropriate situations
&lt;/h4&gt;

&lt;p&gt;A snowflake schema may be appropriate when the source data is already highly normalized or when complex hierarchies and reduced data redundancy are important.&lt;/p&gt;

&lt;h4&gt;
  
  
  Power BI implications
&lt;/h4&gt;

&lt;p&gt;Snowflake schemas can work in Power BI, but the additional relationships can make the model more complex. For many Power BI reports, a star schema is easier to use and maintain.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Fact Tables and Dimension Tables
&lt;/h1&gt;

&lt;p&gt;Every table in your model falls into one of these categories&lt;/p&gt;

&lt;h2&gt;
  
  
  Fact Tables: The “What Happened” Tables
&lt;/h2&gt;

&lt;p&gt;Fact tables contain measurable business events; the transactions, the actions, the things you want to count or sum.&lt;/p&gt;

&lt;h4&gt;
  
  
  Characteristics:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Mostly numbers and IDs (very little text)&lt;/li&gt;
&lt;li&gt;Many rows (thousands to millions)&lt;/li&gt;
&lt;li&gt;Each row is an event or transaction&lt;/li&gt;
&lt;li&gt;Grows over time (new rows added constantly)&lt;/li&gt;
&lt;li&gt;Contains the data you want to measure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a sales fact table might contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sale ID&lt;/li&gt;
&lt;li&gt;Date ID&lt;/li&gt;
&lt;li&gt;Customer ID&lt;/li&gt;
&lt;li&gt;Product ID&lt;/li&gt;
&lt;li&gt;Location ID&lt;/li&gt;
&lt;li&gt;Quantity sold&lt;/li&gt;
&lt;li&gt;Sales amount&lt;/li&gt;
&lt;li&gt;Discount&lt;/li&gt;
&lt;li&gt;Profit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The numeric values represent measurable business events. For example, Quantity Sold can be added to determine total units sold, while Sales Amount can be summed to calculate total revenue.&lt;/p&gt;

&lt;p&gt;Common examples include &lt;em&gt;FactSales, FactOrders, FactTransactions, and FactProduction.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Fact tables normally contains &lt;strong&gt;numeric values (measures)&lt;/strong&gt; and &lt;strong&gt;foreign keys&lt;/strong&gt; that connect the facts to relevant dimension tables. The dimension key columns determine the dimensionality of a fact table, while the dimension key values determine the granularity of a fact table.&lt;/p&gt;

&lt;h4&gt;
  
  
  Grain or Granularity
&lt;/h4&gt;

&lt;p&gt;The grain of a fact table describes exactly what one row represents. Defining the grain is important because it determines what can be accurately measured.&lt;/p&gt;

&lt;p&gt;For example, consider a fact table designed to store sale targets that has two dimension key columns; &lt;em&gt;Date and ProductKey&lt;/em&gt;. It's easy to understand that the table has two dimensions. The granularity, however, can't be determined without considering the dimension key values. In this example, consider that the values stored in the Date column are the first day of each month. In this case, the granularity is at month-product level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dimension Tables: The Who, What, When, Where Tables
&lt;/h2&gt;

&lt;p&gt;Dimension tables contain descriptive information that gives context to your facts. They’re the details that help you slice, filter, and group your measures. The most consistent table you'll find in a star schema is a date dimension table. &lt;/p&gt;

&lt;p&gt;A dimension table contains a key column (or columns) that acts as a unique identifier, and other columns. Other columns support filtering and grouping your data&lt;/p&gt;

&lt;h4&gt;
  
  
  Characteristics:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Mostly text and categories&lt;/li&gt;
&lt;li&gt;Fewer rows (dozens to thousands)&lt;/li&gt;
&lt;li&gt;Relatively stable (changes infrequently)&lt;/li&gt;
&lt;li&gt;Contains the attributes you filter and group by&lt;/li&gt;
&lt;li&gt;Provides the “story” around the numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;DimCustomer&lt;/em&gt; – Customer ID, customer name, gender, age group, city and customer segment.&lt;br&gt;
&lt;em&gt;DimProduct&lt;/em&gt; – Product ID, product name, category, brand and product type.&lt;br&gt;
&lt;em&gt;DimDate&lt;/em&gt; – Date ID, date, day, month, quarter and year.&lt;br&gt;
&lt;em&gt;DimLocation&lt;/em&gt; – Location ID, county, sub-county, region and country.&lt;/p&gt;

&lt;p&gt;For example, a DimProduct table allows users to analyse sales by product, category or brand, while DimDate allows sales to be analysed by month, quarter or year.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to Tell Them Apart
&lt;/h4&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does each row represent a transaction or event?
Yes → Fact table
No → Dimension table&lt;/li&gt;
&lt;li&gt;Will this table grow significantly over time?
Yes → Probably a fact table (new sales every day)
No → Probably a dimension (your product list doesn’t double every week)&lt;/li&gt;
&lt;li&gt;Am I measuring this or describing something?
Measuring → Fact (measuring sales amounts)
Describing → Dimension (describing what products are)&lt;/li&gt;
&lt;li&gt;Does this table have mostly numbers or mostly text?
Numbers → Fact
Text → Dimension&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fco2bxhhrorojmilxmysa.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%2Fco2bxhhrorojmilxmysa.png" alt="Fact and Dimension" width="521" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  A real scenario
&lt;/h5&gt;

&lt;p&gt;You're building a report on Kenyan crop harvests. Here's the data:&lt;/p&gt;

&lt;p&gt;1.Harvest records: 500 rows, growing every season as new harvests are logged. This is a fact table. Each row is a transaction, a farmer's harvest of a crop, with numeric outcomes like yield, revenue, cost, and profit.&lt;/p&gt;

&lt;p&gt;2.Farmer list: grows slowly, but each farmer's name and contact only need to be stored once. This is a dimension table.&lt;/p&gt;

&lt;p&gt;3.County list: around 12 counties, essentially fixed. This is a dimension table.&lt;/p&gt;

&lt;p&gt;4.Crop catalog: crop type and crop variety, a short list that only changes when a new crop is introduced. This is a dimension table.&lt;/p&gt;

&lt;p&gt;5.Seasonal price snapshot: if average market price per crop per county were captured at the start of every season, that's a recurring snapshot of a state at a point in time, similar to an inventory snapshot. It counts as a fact table, even though it's "just prices."&lt;/p&gt;

&lt;p&gt;Table size doesn't decide fact vs dimension. DimFarmer could eventually hold more rows than a small fact table starts with, and it's still a dimension, because each farmer is described once. FactHarvest is a fact table because each row represents something that happened, not something being described.&lt;/p&gt;

&lt;h3&gt;
  
  
  The connection
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Measures versus Descriptive Attributes
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Fact tables&lt;/strong&gt; contain &lt;strong&gt;&lt;em&gt;numerical values&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;metrics&lt;/em&gt;&lt;/strong&gt; used for summarization while &lt;strong&gt;Dimension tables&lt;/strong&gt; contain &lt;strong&gt;&lt;em&gt;descriptive attributes&lt;/em&gt;&lt;/strong&gt; used for filtering or grouping&lt;/p&gt;

&lt;p&gt;Fact tables sit at the center of the model. Dimensions surround them and provide the context to filter by.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Measure:&lt;/strong&gt; Total Profit = SUM(FactHarvest[Profit (KES)])&lt;br&gt;
&lt;strong&gt;Filter:&lt;/strong&gt; County = "Kiambu" (from DimCounty)&lt;br&gt;
&lt;strong&gt;Result:&lt;/strong&gt; total profit earned by Kiambu farmers specifically&lt;/p&gt;

&lt;p&gt;The relationship between FactHarvest and DimCounty is what makes that filter work. Without it, county would just be text sitting in the fact table with nothing to slice it by.&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Relationships in Power BI
&lt;/h1&gt;

&lt;p&gt;Relationships are the invisible bridges between your tables, letting Power BI treat them as connected without merging them into one table.&lt;br&gt;
Without relationships, Power BI treats your tables as completely separate islands.&lt;/p&gt;

&lt;p&gt;With proper relationships:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Filter by customer name&lt;/strong&gt; → automatically filters their sales&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slice by product category&lt;/strong&gt; → sees all products in that category&lt;/li&gt;
&lt;li&gt;Your measures calculate correctly&lt;/li&gt;
&lt;li&gt;Visuals respond to each other&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;In Excel&lt;/strong&gt;, if you want to show customer names next to sales amounts, you use VLOOKUP. Then you copy that formula down 10,000 rows. If customer names change, your VLOOKUP might break. If you sort one column, the VLOOKUPs don’t update.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Power BI&lt;/strong&gt;, you create the relationship once. The relationship handles everything else. No copying formulas. No broken references when data update&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of Relationships
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. One-to-Many (1:*)
&lt;/h3&gt;

&lt;p&gt;One record on one side connects to many records on the other side. DimFarmer to FactHarvest is a good example: one farmer, many harvest records across seasons. The same applies to DimCounty and DimCrop connecting to FactHarvest. Use it whenever a dimension describes something the fact table records repeatedly.&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%2Fp8qyj0js2ldzaq0wxhby.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%2Fp8qyj0js2ldzaq0wxhby.png" alt="one to many" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. One-to-one (1:1)
&lt;/h3&gt;

&lt;p&gt;Each row on one side matches exactly one row on the other, with no repeats either way. This is uncommon in practice. An example here would be if Farmer Contact were split into its own table, with exactly one contact record per farmer, that would be 1:1. Usually it's a sign the two tables should just be combined instead.&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%2Fgs3bevny024jhekqqhk7.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%2Fgs3bevny024jhekqqhk7.png" alt="one to one" width="800" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Many-to-many (:)
&lt;/h3&gt;

&lt;p&gt;Rows on either side can match multiple rows on the other. An example from this dataset would be Pest Control method versus Crop Type, where a crop can use several methods, and a method applies to several crops. This should be used carefully, since it can cause ambiguous filtering, and is often better resolved with a bridge table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Farllzf8l9avjn2bon8ac.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%2Farllzf8l9avjn2bon8ac.png" alt="many to many" width="800" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Keys:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Primary key:&lt;/strong&gt; uniquely identifies each row in a dimension table, for example FarmerID in DimFarmer, appearing once.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Foreign key:&lt;/strong&gt; the same column shown in the fact table, repeating once per event, for example FarmerID in FactHarvest appearing many times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cardinality:&lt;/strong&gt; the relationship type, whether 1:*, 1:1, or :. tells you how many records on each side can match.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Referential integrity:&lt;/strong&gt; every foreign key in the fact table must have a matching primary key in the dimension table, otherwise that row gets excluded from analysis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Active and inactive relationships:&lt;/strong&gt; Power BI only allows one active relationship between two tables at a time. If FactHarvest had both a Planting Date and a Harvest Date needing to relate to DimDate, only one would stay active by default, and the other would need USERELATIONSHIP() in DAX to be used.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  4. Filter Direction In Power BI
&lt;/h1&gt;

&lt;h4&gt;
  
  
  What It Means
&lt;/h4&gt;

&lt;h6&gt;
  
  
  Controls how filters travel between tables.
&lt;/h6&gt;

&lt;p&gt;&lt;strong&gt;"Both"&lt;/strong&gt; lets filters flow both ways; &lt;br&gt;
&lt;strong&gt;"Single" (or "One direction")&lt;/strong&gt; only lets filters flow from the one-side (usually a dimension) to the many-side (usually a fact). 99% of the time you should have single direction filters.&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%2Fescquhzpp4pya5e2d2nb.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%2Fescquhzpp4pya5e2d2nb.png" alt="Filters" width="479" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Affects which visuals and slicers interact.
&lt;/h6&gt;

&lt;p&gt;Bidirectional can make slicers reduce available values across unrelated tables, but it can also create ambiguous filter paths and wrong results. It's generally considered a bad practice as bi-directional relationships can create ambiguity between tables which can lead DAX measures to return false results.&lt;/p&gt;

&lt;h6&gt;
  
  
  Used only for special cases like many-to-many or bridging.
&lt;/h6&gt;

&lt;p&gt;Some scenarios (bridge tables, many-to-many) require BOTH to get the expected slicer behavior, but it increases complexity and risk. &lt;/p&gt;

&lt;h4&gt;
  
  
  Why It Matters
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Affects model correctness and predictability.&lt;/strong&gt; Too many bidirectional filters create ambiguous paths and unpredictable results as the engine decides how to apply filters. Too many bidirectional filters and PBI will decide how to apply these filters, this might lead to un-predictable results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impacts performance and maintenance.&lt;/strong&gt; Using measures or virtual filters instead of physical bidirectional relationships can work but adds complexity and may hurt performance. &lt;br&gt;
There are DAX workarounds when BOTH is undesirable. Techniques like &lt;code&gt;ISEMPTY&lt;/code&gt;, &lt;code&gt;TREATAS&lt;/code&gt;, or measure-level logic can simulate slicer-to-slicer behavior without enabling bidirectional everywhere. &lt;/p&gt;

&lt;h4&gt;
  
  
  Practical Guidance
&lt;/h4&gt;

&lt;p&gt;Default to single direction for star schemas. Keep dimensions filtering facts; avoid BOTH unless needed.  &lt;/p&gt;

&lt;h5&gt;
  
  
  When to use Both:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Row-level security requirements&lt;/li&gt;
&lt;li&gt;Specific many-to-many scenarios with bridge tables&lt;/li&gt;
&lt;li&gt;You have a clear business reason and understand the impact&lt;/li&gt;
&lt;li&gt;Use BOTH for true many-to-many or bridge-table patterns. When a bridge or many-to-many scenario requires slicers to cascade across facts, BOTH is acceptable but document and test carefully. &lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Why to avoid Both (Bi-Directional):
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Slower performance&lt;/li&gt;
&lt;li&gt;Unexpected filtering behavior that confuses users&lt;/li&gt;
&lt;li&gt;Higher risk of circular dependencies&lt;/li&gt;
&lt;li&gt;Harder to debug when things go wrong
#####The rule:
Always start with Single. Only change to Both if you have a specific, documented reason.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prefer explicit DAX if you need controlled behavior. Use measures that check activity (&lt;code&gt;ISEMPTY&lt;/code&gt;) or &lt;code&gt;TREATAS&lt;/code&gt; to make filter logic explicit and avoid ambiguous model paths.  &lt;/p&gt;

&lt;h1&gt;
  
  
  6.Joins in Power Query
&lt;/h1&gt;

&lt;p&gt;In Power Query, joins combine two tables based on matching values in one or more columns. When the compared row values between two tables are identical, they are considered a match. The behavior that follows depends on the join type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Merge Queries in Power Query
&lt;/h2&gt;

&lt;p&gt;The easiest way to join tables in Power Query is by using merge queries. &lt;br&gt;
To start, go to the Home tab in the ribbon and navigate to the Combine section. There you will find the Merge Queries button. There are two options as below:&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%2Fpl5az0773838n9cyfgxl.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%2Fpl5az0773838n9cyfgxl.png" alt="merge" width="599" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Merge Queries&lt;/strong&gt; performs a join on your current table and adds the result of this merge in the same query. This means you can easily see the impact of the merge in a single place.&lt;br&gt;
&lt;strong&gt;Option 2: Merge Queries as New&lt;/strong&gt; performs the same join on your table but puts the result of the merge in a separate query. The benefit of this approach is that your starting query remains the same. This means that you can reference that starting query for other purposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  JOIN TYPES
&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%2F8herm0po35aamrj8486y.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%2F8herm0po35aamrj8486y.png" alt="Join Types" width="667" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The most common join. It returns all rows from the left table. Then, by matching one or more column values with rows from the left table with similar columns from rows in the right table, the join returns the matching values of the right table.&lt;br&gt;
The Left Outer Join is often used when combining information from different tables that have a unique key to match. Power Query uses &lt;code&gt;JoinKind.LeftOuter&lt;/code&gt; &lt;/p&gt;

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

&lt;p&gt;The Right Outer Join returns all values from the Right Table while only returning the matching values from the Left Table. Its behavior is very similar to the Left Outer join, except that its base table is the Right table instead of the Left. It uses &lt;code&gt;JoinKind.RightOuter&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;The Full Outer Join tries to match column values from the left table with the right table and if successful, puts them next to each other. The values of the left table that don’t exist in the right table get their own row. Any rows without a match in the right table return null values for these rows. Similarly, the values of the right table that don’t exist in the left table also get their own row. For these rows, the missing columns from the left table get null values. To perform a Full Outer Join, you can make use of the join type &lt;code&gt;JoinKind.FullOuter&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;The Left Anti Join only returns rows from the Left Table. Based on the key columns, the join searches for which values in the left table do not exist in the right table. It then only returns the unique values from the left table. The Left Anti Join is a great way to perform checks on your queries. You can instruct Power Query a Left Anti Join by using &lt;code&gt;JoinKind.LeftAnti&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  e) Right Anti Join
&lt;/h3&gt;

&lt;p&gt;The Right Anti-Join is the twin sister of the Left Anti-Join. It returns the rows from the Right Table which are not present in the Left Table. To do that, it uses &lt;code&gt;JoinKind.RightAnti&lt;/code&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  When to use Left Anti Join or Right Anti Join
&lt;/h5&gt;

&lt;p&gt;The choice of which of the two joins to perform depends on where in your queries you want to see the result. If you quickly want to compare which values of another table are not present in the current table, the Right Anti Join lets you do it right away.&lt;br&gt;
Yet if you want to see which values of the current table miss in another, the Left Anti Join lets you hit the ground running.&lt;/p&gt;

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

&lt;p&gt;The Inner Join is a useful join that returns only those rows that have matching values in both the Left Table and the Right Table. This can be useful when creating tables for your data model. &lt;/p&gt;

&lt;h1&gt;
  
  
  6. Power Query Joins vs Power BI Relationships
&lt;/h1&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%2Fyfq1alwvpkf0rsb72haf.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%2Fyfq1alwvpkf0rsb72haf.png" alt="PQPBI" width="560" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Joins
&lt;/h2&gt;

&lt;p&gt;In Power BI, you can use joins to physically combine tables based on common columns. This approach is ideal for smaller datasets or when specific aggregations on combined data are required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros of Using Joins:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Simplicity: Joins are straightforward to implement, especially for users with a SQL background.&lt;/li&gt;
&lt;li&gt;Aggregations: Enables direct aggregations on denormalized data for certain analysis needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons of Using Joins:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Redundancy: Joins can lead to data redundancy and increased memory usage.&lt;/li&gt;
&lt;li&gt;Limited Flexibility: May not be suitable for scenarios requiring a more normalized data model.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Power BI’s relationships offer a more sophisticated approach, allowing you to establish logical links between tables without physically combining them. This is particularly beneficial for larger datasets or when maintaining a normalized data model is essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros of Using Relationships:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Data Integrity: Relationships help maintain data integrity by avoiding unnecessary duplication.&lt;/li&gt;
&lt;li&gt;Flexibility: Provides a more flexible data model, allowing for better scalability and adaptability.&lt;/li&gt;
&lt;li&gt;Performance: Generally, relationships perform better with larger datasets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons of Using Relationships:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Complexity: Setting up relationships might be more complex, especially for those new to Power BI.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Learning Curve: Understanding the nuances of relationships requires a learning curve for some users.&lt;/p&gt;
&lt;h3&gt;
  
  
  Choosing the Right Approach:
&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider Data Volume: For large datasets, relationships are generally more efficient in terms of performance and storage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normalization Matters: If your goal is to maintain a normalized data model for better integrity and flexibility, relationships are the preferred choice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User Experience: Think about how end users will interact with the data. Relationships provide a seamless experience for drilling down into related data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Analysis Requirements: If your analysis involves aggregations and calculations that necessitate a denormalized dataset, joining tables might be more suitable.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, In the dynamic landscape of Power BI, choosing between joins and relationships is a pivotal decision that shapes the efficiency and effectiveness of your data modeling. &lt;/p&gt;

&lt;p&gt;Whether you opt for the simplicity of joins or the sophistication of relationships depends on the specific needs of your project. &lt;/p&gt;

&lt;p&gt;By understanding the strengths and weaknesses of each approach, you can elevate your Power BI skills and create compelling, insightful reports.&lt;/p&gt;

&lt;h1&gt;
  
  
  7. Recommended Power BI Model
&lt;/h1&gt;

&lt;p&gt;For most Power BI analytical and business intelligence projects, a &lt;strong&gt;Star Schema&lt;/strong&gt; is generally recommended. It provides a clear separation between fact tables, which contain measurable business events, and dimension tables, which contain descriptive information.&lt;/p&gt;

&lt;p&gt;A typical Power BI model may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FactSales – contains sales transactions, quantities, revenue, costs and other measurable values.&lt;/li&gt;
&lt;li&gt;DimCustomer – contains customer information such as customer name, location and customer category.&lt;/li&gt;
&lt;li&gt;DimProduct – contains product information such as product name, category, brand and product type.&lt;/li&gt;
&lt;li&gt;DimDate – contains dates, months, quarters and years.&lt;/li&gt;
&lt;li&gt;DimLocation – contains geographical information such as city, region and country.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fact table is connected to the dimension tables through relationships, typically using a one-to-many relationship from each dimension to the fact table.&lt;/p&gt;

&lt;p&gt;The star schema is recommended because it provides a good balance between performance, simplicity, scalability and ease of use. It also makes it easier to create Power BI reports, write DAX measures and allow users to filter and analyse business data.&lt;/p&gt;

&lt;p&gt;A flat table may be suitable for small and simple reports, while a snowflake schema may be appropriate when highly normalized data structures or complex hierarchies are required. However, for most Power BI reporting scenarios, the star schema provides a more practical and user-friendly model.&lt;/p&gt;

</description>
      <category>data</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building an Interactive Excel Dashboard for E-commerce Product Analysis: A Case Study of Jumia Products</title>
      <dc:creator>Wendy Ochieng</dc:creator>
      <pubDate>Sat, 05 Sep 2026 11:13:15 +0000</pubDate>
      <link>https://dev.to/wendy_ochieng/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-case-study-of-jumia-14oh</link>
      <guid>https://dev.to/wendy_ochieng/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-case-study-of-jumia-14oh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction &amp;amp; Objective
&lt;/h2&gt;

&lt;p&gt;E-commerce platforms generate a constant stream of pricing, promotion, and customer-feedback data. But raw data on its own doesn't tell a seller anything useful. For this project, I&lt;br&gt;
built an interactive Excel dashboard using a Jumia product dataset to answer a set of&lt;br&gt;
practical business questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are larger discounts associated with more customer reviews?&lt;/li&gt;
&lt;li&gt;Do highly rated products attract stronger engagement?&lt;/li&gt;
&lt;li&gt;Do price and rating move together?&lt;/li&gt;
&lt;li&gt;Which products are performing best, and which need a different pricing or marketing
strategy?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Importantly, this dataset doesn't include units sold or revenue, so &lt;strong&gt;review count was used&lt;br&gt;
throughout as a proxy for customer engagement&lt;/strong&gt; and not as a stand-in for sales. That distinction&lt;br&gt;
mattered for how I framed every insight later in the project.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dataset Description
&lt;/h2&gt;

&lt;p&gt;The source file, &lt;code&gt;Excel_jumia_dataset.csv&lt;/code&gt;, contained the following fields:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Expected type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Product&lt;/td&gt;
&lt;td&gt;Product name&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Current price&lt;/td&gt;
&lt;td&gt;Selling price (KSh)&lt;/td&gt;
&lt;td&gt;Number/currency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Old price&lt;/td&gt;
&lt;td&gt;Price before discount (KSh)&lt;/td&gt;
&lt;td&gt;Number/currency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discount&lt;/td&gt;
&lt;td&gt;Advertised % discount&lt;/td&gt;
&lt;td&gt;Percentage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Number of customer reviews&lt;/td&gt;
&lt;td&gt;Whole number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ratingd &lt;em&gt;(sic)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Average rating out of 5&lt;/td&gt;
&lt;td&gt;Decimal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Before touching anything, I ran a data-quality audit and found several issues typical of&lt;br&gt;
scraped e-commerce data: a ## Introduction &amp;amp; Objective&lt;/p&gt;

&lt;p&gt;E-commerce platforms generate a constant stream of pricing, promotion, and customer-feedback data. But raw data on its own doesn't tell a seller anything useful. For this project, I&lt;br&gt;
built an interactive Excel dashboard using a Jumia product dataset to answer a set of&lt;br&gt;
practical business questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are larger discounts associated with more customer reviews?&lt;/li&gt;
&lt;li&gt;Do highly rated products attract stronger engagement?&lt;/li&gt;
&lt;li&gt;Do price and rating move together?&lt;/li&gt;
&lt;li&gt;Which products are performing best, and which need a different pricing or marketing
strategy?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Importantly, this dataset doesn't include units sold or revenue, so &lt;strong&gt;review count was used&lt;br&gt;
throughout as a proxy for customer engagement&lt;/strong&gt; and not as a stand-in for sales. That distinction&lt;br&gt;
mattered for how I framed every insight later in the project.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dataset Description
&lt;/h2&gt;

&lt;p&gt;The source file, &lt;code&gt;Excel_jumia_dataset.csv&lt;/code&gt;, contained the following fields:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Expected type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Product&lt;/td&gt;
&lt;td&gt;Product name&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Current price&lt;/td&gt;
&lt;td&gt;Selling price (KSh)&lt;/td&gt;
&lt;td&gt;Number/currency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Old price&lt;/td&gt;
&lt;td&gt;Price before discount (KSh)&lt;/td&gt;
&lt;td&gt;Number/currency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discount&lt;/td&gt;
&lt;td&gt;Advertised % discount&lt;/td&gt;
&lt;td&gt;Percentage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Number of customer reviews&lt;/td&gt;
&lt;td&gt;Whole number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ratingd &lt;em&gt;(sic)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Average rating out of 5&lt;/td&gt;
&lt;td&gt;Decimal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Before touching anything, I ran a data-quality audit and found several issues typical of&lt;br&gt;
scraped e-commerce data: misspelled header (&lt;code&gt;Ratingd&lt;/code&gt;), blank cells in the review and&lt;br&gt;
rating columns, negative review counts, at least one price expressed as a range instead of a&lt;br&gt;
single number, and duplicate rows.&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%2Fq049utgunab2zxu3f63p.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%2Fq049utgunab2zxu3f63p.png" alt="Raw Jumia product dataset showing unedited price, discount, review, and rating columns" width="780" height="272"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Data Cleaning &amp;amp; Preparation
&lt;/h2&gt;

&lt;p&gt;I kept &lt;code&gt;Raw_Data&lt;/code&gt; completely untouched as a permanent reference and did all cleaning in a&lt;br&gt;
duplicated query, using &lt;strong&gt;Power Query&lt;/strong&gt; for the transformations (with a few native Excel&lt;br&gt;
formulas where they were simpler).&lt;/p&gt;

&lt;p&gt;Key cleaning decisions, all logged in a &lt;code&gt;Data_Dictionary&lt;/code&gt; sheet with an Issue → Rows&lt;br&gt;
Affected → Decision → Reason structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Header fix:&lt;/strong&gt; &lt;code&gt;Ratingd&lt;/code&gt; renamed to &lt;code&gt;Rating&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Currency cleanup:&lt;/strong&gt; Stripped "KSh" and thousands-separator commas from price fields, then converted to Decimal Number.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price range:&lt;/strong&gt; One row contained a range (e.g. &lt;code&gt;"1620 - 1980"&lt;/code&gt;) instead of a single price.
Rather than deleting or guessing, I used the &lt;strong&gt;midpoint&lt;/strong&gt; — &lt;code&gt;(1620+1980)/2 = 1800&lt;/code&gt; — and
documented the original value and decision in the cleaning log.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discount:&lt;/strong&gt; Power Query correctly auto-typed this column as Percentage, so no extra &lt;code&gt;/100&lt;/code&gt; conversion was needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Negative reviews:&lt;/strong&gt; Treated the negative sign as a scraping artifact and converted to
absolute values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing values:&lt;/strong&gt; Left genuinely blank ratings/reviews as blank rather than assuming zero or imputing an average.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicates:&lt;/strong&gt; Removed only rows that matched exactly across all relevant fields, so that legitimate same-name listings with different prices or feedback weren't accidentally dropped.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After cleaning, I ran validation formulas directly on the Excel Table (&lt;code&gt;tblProducts&lt;/code&gt;) to catch&lt;br&gt;
anything that slipped through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=IF(OR([@Rating]&amp;lt;0,[@Rating]&amp;gt;5),"Check rating","OK")
=IF(OR([@Discount]&amp;lt;0,[@Discount]&amp;gt;1),"Check discount","OK")
=IF([@[Current Price]]&amp;gt;[@[Old Price]],"Check prices","OK")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F0f6ikmvup6eygm1z5iht.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%2F0f6ikmvup6eygm1z5iht.png" alt="Cleaned product data table with standardized price, discount, review, and rating columns" width="780" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Excel Techniques, Formulas &amp;amp; Analysis
&lt;/h2&gt;

&lt;p&gt;With clean data in place, I enriched the table with derived fields and category flags, all&lt;br&gt;
using &lt;strong&gt;fixed, stated thresholds&lt;/strong&gt; rather than subjective judgment calls, so any result could&lt;br&gt;
be reproduced by rerunning the same formulas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discount amount&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=[@[Old Price]]-[@[Current Price]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rating category&lt;/strong&gt; (Poor &amp;lt;3, Average 3–4.5, Excellent &amp;gt;4.5)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=IF([@Rating]="","Missing",IF([@Rating]&amp;lt;3,"Poor",IF([@Rating]&amp;lt;=4.5,"Average","Excellent")))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Discount category&lt;/strong&gt; (Low &amp;lt;20%, Medium 20–40%, High &amp;gt;40%)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=IF([@Discount]="","Missing",IF([@Discount]&amp;lt;20%,"Low Discount",IF([@Discount]&amp;lt;=40%,"Medium Discount","High Discount")))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Price category&lt;/strong&gt;, based on quartiles rather than arbitrary cutoffs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Price_Q1 = QUARTILE.INC(tblProducts[Current Price],1)
Price_Q3 = QUARTILE.INC(tblProducts[Current Price],3)
=IF([@[Current Price]]="","Missing",IF([@[Current Price]]&amp;lt;=Price_Q1,"Low Price",IF([@[Current Price]]&amp;lt;=Price_Q3,"Medium Price","High Price")))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Engagement threshold&lt;/strong&gt;, defined as the 75th percentile of review counts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=PERCENTILE.INC(tblProducts[Review],0.75)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there, I built four flag columns to surface specific, actionable product segments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High Discount + Poor Rating. Discounting isn't fixing an underlying quality problem&lt;/li&gt;
&lt;li&gt;High Discount + Weak Engagement. the discount isn't converting into visibility&lt;/li&gt;
&lt;li&gt;Strong Engagement + Average Rating. popular but not loved, room for improvement &lt;/li&gt;
&lt;li&gt;Strong Engagement + Excellent Rating. the benchmark performers worth promoting further&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Correlation analysis
&lt;/h3&gt;

&lt;p&gt;I tested three relationships using &lt;code&gt;CORREL()&lt;/code&gt; and matching scatter plots with trendlines:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Relationship&lt;/th&gt;
&lt;th&gt;Correlation (r)&lt;/th&gt;
&lt;th&gt;R²&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Discount vs. Reviews&lt;/td&gt;
&lt;td&gt;-0.14&lt;/td&gt;
&lt;td&gt;0.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rating vs. Reviews&lt;/td&gt;
&lt;td&gt;0.06&lt;/td&gt;
&lt;td&gt;0.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price vs. Rating&lt;/td&gt;
&lt;td&gt;0.11&lt;/td&gt;
&lt;td&gt;0.01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All three came back weak. It means price,&lt;br&gt;
discount, and rating don't strongly predict customer engagement in this dataset, at least not in a simple linear way.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ranked tables
&lt;/h3&gt;

&lt;p&gt;I used &lt;code&gt;SORT&lt;/code&gt;, &lt;code&gt;FILTER&lt;/code&gt;, and &lt;code&gt;LARGE&lt;/code&gt; to build ranked views: top/bottom 5 by rating, top 10 by&lt;br&gt;
discount, top 10 by reviews, top 10 by rating, and lists of flagged products pulled directly&lt;br&gt;
from the flag columns using &lt;code&gt;FILTER()&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dashboard Creation Process
&lt;/h2&gt;

&lt;p&gt;The dashboard sits on a single sheet, laid out to be readable without scrolling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Title + Slicers
KPI cards (Total Products, Avg Price, Avg Discount, Avg Rating, Total Reviews)
Top 10 tables (by Rating, Reviews, Discount)
Scatter charts (Discount vs Reviews, Rating vs Reviews, Price vs Rating)
Mix charts (Rating Mix, Discount Mix) + Key Insights
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few build details worth mentioning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I used &lt;strong&gt;rounded rectangle shapes&lt;/strong&gt; for the KPI cards rather than plain cells, aligned and
distributed evenly via Excel's Align tools.&lt;/li&gt;
&lt;li&gt;Each KPI number is &lt;strong&gt;linked live to its source cell&lt;/strong&gt; (via the Formula Bar, e.g.
&lt;code&gt;=Analysis!B2&lt;/code&gt;), rather than typed in manually — so the dashboard updates automatically if the
underlying data changes.&lt;/li&gt;
&lt;li&gt;Three &lt;strong&gt;slicers&lt;/strong&gt; (Rating Category, Discount Category, Price Category) are connected to every
relevant PivotTable and PivotChart via Report Connections, and tested individually and in
combination.&lt;/li&gt;
&lt;li&gt;Formatting followed a consistent standard throughout: KSh on prices, % on discounts, one
decimal on ratings, thousands separators on reviews, no 3-D charts, and horizontal bars where
product names were too long for vertical labels.&lt;/li&gt;
&lt;li&gt;A small note box on the dashboard documents the category thresholds, and how missing values were handled.&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%2Fn7yyflgsb3kr8bwweoqm.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%2Fn7yyflgsb3kr8bwweoqm.png" alt="PivotTables summarizing product counts by rating and discount category" width="780" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Insights &amp;amp; Business Recommendations
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discount vs. reviews (r = -0.14, R² = 0.02):&lt;/strong&gt; No meaningful relationship. Sellers shouldn't rely on deeper discounts alone to drive engagement other levers like listing quality, placement, or timing likely matter more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rating vs. reviews (r = 0.06, R² = 0.00):&lt;/strong&gt; Essentially no relationship. A high rating alone doesn't appear to boost visibility; category demand and listing age may play a bigger role.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Price vs. rating (r = 0.11, R² = 0.01):&lt;/strong&gt; Very weak positive relationship. Price shouldn't be treated as a proxy for perceived quality in pricing decisions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;High discount, low rating products:&lt;/strong&gt; A specific subset of products combine heavy discounting with poor ratings. These are stronger candidates for a quality or listing review than for further price cuts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strong engagement, excellent rating products:&lt;/strong&gt; These are the benchmark performers worth using as templates (pricing, description style, imagery) for underperforming listings in the same category.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;A caveat that applies to every finding above:&lt;/strong&gt; correlation is not causation. None of these&lt;br&gt;
relationships account for factors the dataset doesn't capture such as listing age, category,&lt;br&gt;
visibility, or promotional placement so they should inform further investigation, not stand&lt;br&gt;
alone as proof of what's driving performance.&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%2F9hdwfw7dopkqsmddl3bj.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%2F9hdwfw7dopkqsmddl3bj.png" alt="Jumia product performance dashboard with KPI cards, top 10 tables, charts, and slicers" width="780" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;This project reinforced something that's easy to forget when a dashboard looks polished: weak&lt;br&gt;
correlations are still a real, useful finding and not a failed analysis. The value here wasn't in&lt;br&gt;
forcing a dramatic story out of the data, but in cleaning it rigorously, documenting every&lt;br&gt;
decision, and being honest about what the numbers do and don't support.&lt;/p&gt;

&lt;p&gt;The full workbook, dataset, and dashboard screenshots are available in my GitHub repo  linked&lt;br&gt;
below.&lt;/p&gt;

&lt;p&gt;🔗 &lt;em&gt;[&lt;a href="https://github.com/ochiengwendy21-gif/jumia-product-performance-dashboard" rel="noopener noreferrer"&gt;https://github.com/ochiengwendy21-gif/jumia-product-performance-dashboard&lt;/a&gt;]&lt;/em&gt;&lt;/p&gt;

</description>
      <category>analysis</category>
      <category>analytics</category>
      <category>data</category>
    </item>
    <item>
      <title>A beginner's understanding of the Git Workflow</title>
      <dc:creator>Wendy Ochieng</dc:creator>
      <pubDate>Mon, 24 Aug 2026 15:08:10 +0000</pubDate>
      <link>https://dev.to/wendy_ochieng/a-beginners-understanding-of-the-git-workflow-53j8</link>
      <guid>https://dev.to/wendy_ochieng/a-beginners-understanding-of-the-git-workflow-53j8</guid>
      <description>&lt;h2&gt;
  
  
  Git
&lt;/h2&gt;

&lt;p&gt;This is a version control system that tracks changes to files in a project. It's a software that recalls the exact files that were edited, when these changes were made and by whom(if it's a team project) and stores the previous versions of the files.&lt;br&gt;
It's quite useful especially for large projects with multiple developers.&lt;br&gt;
Git saves your files locally(in your machine) and you can store your code online or share it with others through &lt;em&gt;github&lt;/em&gt;, &lt;em&gt;gitlab&lt;/em&gt; or &lt;em&gt;bitbucket&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Git Core Concepts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Repository(Repo)&lt;/strong&gt;&lt;br&gt;
This refers to a project and its entire history of changes. It can be local or remote.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Git commits&lt;/strong&gt;&lt;br&gt;
These are like snapshots of the entire projects that records all the tracked changes in your directory. Git can sometimes bundle all the changes to a project from one version of the repository to another, instead of just blindly copying the entire directory every time you commit-it maintains a history of which commits were made when.&lt;br&gt;
A new commit might have another commit above it, like a parent commit, which references which commit it was based off of.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Git Branches&lt;/strong&gt;&lt;br&gt;
These are simply pointers to a specific commit. They are independent lines of development that allows you to work on features or fixes without affecting others.&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%2F17bnalc7zeg3v670k8vs.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%2F17bnalc7zeg3v670k8vs.png" alt="Git Workflow Diagram.com" width="253" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the image, we have a branch called &lt;em&gt;newimage&lt;/em&gt; that now refers to commit &lt;em&gt;C1&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To create a branch called &lt;em&gt;newimage&lt;/em&gt; and immediately switch to it, we can use this code;&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;git checkout -b newimage&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;To prevent having many branches, it's better to divide your work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Merge&lt;/strong&gt;&lt;br&gt;
Merging brings changes from one branch into another.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Git Workflow
&lt;/h2&gt;

&lt;p&gt;Common commands used to manage projects and upload your work to github.&lt;br&gt;
&lt;strong&gt;1. Working Directory&lt;/strong&gt;&lt;br&gt;
This is the local folder where you create, open and edit files. This directory can be observed but changes are not automatically recorded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Staging Area&lt;/strong&gt;&lt;br&gt;
This is where you select the changes you want to include in your next commit. You may choose specific files or lines of code you want to bundle together before saving.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Local Repository&lt;/strong&gt;&lt;br&gt;
It's the internal git database inside the project folder. It's where you commit the staged changes and git permanently saves it as a secure snapshot in your local history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Remote Repository&lt;/strong&gt;&lt;br&gt;
This is where commits are pushed so others can access them, eg Github.&lt;/p&gt;

&lt;p&gt;Note; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You &lt;strong&gt;push&lt;/strong&gt; projects from your local machine to Github&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;pull&lt;/strong&gt; projects from Github to your local machine&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The workflow looks like this in a nutshell;&lt;br&gt;
┌──────────────────┐&lt;br&gt;
│ Working Directory│&lt;br&gt;
│ (your files)     │&lt;br&gt;
└─────────┬────────┘&lt;br&gt;
          │&lt;br&gt;
          │ git add &lt;br&gt;
          │ git add.&lt;br&gt;
          ▼&lt;br&gt;
┌──────────────────┐&lt;br&gt;
│  Staging Area    │&lt;br&gt;
│   (index)        │&lt;br&gt;
└─────────┬────────┘&lt;br&gt;
          │&lt;br&gt;
          │ git commit -m "message"&lt;br&gt;
          ▼&lt;br&gt;
┌──────────────────┐&lt;br&gt;
│ Local Repository │&lt;br&gt;
│ (your computer)  │&lt;br&gt;
└─────────┬────────┘&lt;br&gt;
          │&lt;br&gt;
          │ git push origin main&lt;br&gt;
          ▼&lt;br&gt;
┌──────────────────┐&lt;br&gt;
│Remote Repository │&lt;br&gt;
│ GitHub / GitLab  │&lt;br&gt;
└─────────┬────────┘&lt;br&gt;
          ▲&lt;br&gt;
          │&lt;br&gt;
          │ git pull origin main&lt;br&gt;
          │ git fetch&lt;br&gt;
          │&lt;br&gt;
          └───────────────────────&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edit files in the Working Directory.&lt;/li&gt;
&lt;li&gt;Use git add to move changes to the Staging Area.&lt;/li&gt;
&lt;li&gt;Use git commit to save a snapshot in the Local Repository.&lt;/li&gt;
&lt;li&gt;Use git push to send commits to GitHub.&lt;/li&gt;
&lt;li&gt;Use git pull to get other developers' latest changes.&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
  </channel>
</rss>
