<?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: SAMWEL SHIHANDE</title>
    <description>The latest articles on DEV Community by SAMWEL SHIHANDE (@samwel_shihande_3b29d4559).</description>
    <link>https://dev.to/samwel_shihande_3b29d4559</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%2F4071724%2F68bb44ce-bddb-4d72-b75a-74ebcafb45eb.jpg</url>
      <title>DEV Community: SAMWEL SHIHANDE</title>
      <link>https://dev.to/samwel_shihande_3b29d4559</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/samwel_shihande_3b29d4559"/>
    <language>en</language>
    <item>
      <title>Data Modelling, Relationships and Joins in Power BI: A Practical Guide</title>
      <dc:creator>SAMWEL SHIHANDE</dc:creator>
      <pubDate>Sun, 20 Sep 2026 08:58:43 +0000</pubDate>
      <link>https://dev.to/samwel_shihande_3b29d4559/data-modelling-relationships-and-joins-in-power-bi-a-practical-guide-372c</link>
      <guid>https://dev.to/samwel_shihande_3b29d4559/data-modelling-relationships-and-joins-in-power-bi-a-practical-guide-372c</guid>
      <description>&lt;p&gt;A Power BI report is only as good as the model underneath it. I have seen beautiful dashboards give wrong totals, and simple-looking reports crawl for minutes, and the cause is almost always the same: a poorly designed data model. In this article I walk through how data modelling works in Power BI, how to compare flat, star and snowflake schemas, how relationships and filter direction behave, how joins work in Power Query, and how I would design a model for a real business intelligence project.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Data Modelling in Power BI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is data modelling?
&lt;/h3&gt;

&lt;p&gt;Data modelling in Power BI is the process of deciding &lt;strong&gt;which tables you need, what each table contains, and how those tables relate to each other&lt;/strong&gt;. The model lives in the Model view of Power BI Desktop. It is the layer between your raw data sources and your visuals.&lt;/p&gt;

&lt;p&gt;Power BI's engine (VertiPaq) stores data in memory in a compressed, column-based format. DAX calculations work by applying &lt;em&gt;filter context&lt;/em&gt; that travels across relationships between tables. So the way you structure tables and relationships directly decides how fast reports run and whether the numbers are right.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why a well-designed model matters
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reporting and analytics:&lt;/strong&gt; Slicers, matrices and charts behave predictably when filters flow cleanly from descriptive tables to numeric tables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DAX calculations:&lt;/strong&gt; Measures are short and readable when the model is clean. A messy model forces long, defensive DAX with lots of &lt;code&gt;FILTER&lt;/code&gt;, &lt;code&gt;ALL&lt;/code&gt; and &lt;code&gt;CROSSFILTER&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Smaller, narrower tables with fewer repeated text values compress better and scan faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; When new data sources, new metrics or new years arrive, a good model absorbs them without a rebuild.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability:&lt;/strong&gt; A change such as renaming a product category happens in one place, not in millions of rows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The three common approaches
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1.1 Flat table
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; Everything is stored in one wide table. Sales figures, customer details, product details and dates all sit on the same row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure:&lt;/strong&gt; One table, many columns. Each row repeats all descriptive information.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;erDiagram
    FlatSales {
        int OrderID
        date OrderDate
        string CustomerName
        string CustomerCity
        string ProductName
        string Category
        string StoreName
        int Quantity
        decimal SalesAmount
    }&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very quick to build, with no relationships to manage.&lt;/li&gt;
&lt;li&gt;Easy to understand for small datasets and one-off analysis.&lt;/li&gt;
&lt;li&gt;Works well when the source is already a single CSV or Excel export.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heavy redundancy. "Nairobi" or "Electronics" is stored again on every row.&lt;/li&gt;
&lt;li&gt;Larger file size and slower refresh as data grows.&lt;/li&gt;
&lt;li&gt;Difficult to add a second business process (for example budgets) without duplicating dimension data.&lt;/li&gt;
&lt;li&gt;Updates to descriptive data are hard to manage.&lt;/li&gt;
&lt;li&gt;DAX for things like distinct customers or time intelligence gets awkward without a proper date table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When it is appropriate:&lt;/strong&gt; Small, one-off analyses, quick prototypes, or a dataset that will never grow or be reused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance and complexity:&lt;/strong&gt; Model complexity is low, but performance and maintainability get worse as the data grows, because repeated text values compress poorly and there are no shared dimensions.&lt;/p&gt;

&lt;h4&gt;
  
  
  1.2 Star schema
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; A star schema has one central &lt;strong&gt;fact table&lt;/strong&gt; surrounded by &lt;strong&gt;dimension tables&lt;/strong&gt;. When drawn, it looks like a star.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure:&lt;/strong&gt; The fact table holds numeric business events and foreign keys. Each dimension holds descriptive attributes and has a unique key. Dimensions connect only to the fact table, never to each other.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;erDiagram
    DimCustomer ||--o{ FactSales : "CustomerID"
    DimProduct ||--o{ FactSales : "ProductID"
    DimDate ||--o{ FactSales : "DateKey"
    DimLocation ||--o{ FactSales : "LocationID"

    FactSales {
        int SalesID PK
        int CustomerID FK
        int ProductID FK
        int DateKey FK
        int LocationID FK
        int Quantity
        decimal SalesAmount
    }
    DimCustomer {
        int CustomerID PK
        string CustomerName
        string Segment
    }
    DimProduct {
        int ProductID PK
        string ProductName
        string Category
        string Brand
    }
    DimDate {
        int DateKey PK
        date Date
        int Year
        string MonthName
    }
    DimLocation {
        int LocationID PK
        string City
        string Region
        string Country
    }&lt;/code&gt;&lt;/pre&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Screenshot placeholder:&lt;/strong&gt; Insert your own Power BI Model view screenshot of the star schema here, with table names and the 1 and * markers on each relationship line visible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple, predictable filter flow: dimension to fact.&lt;/li&gt;
&lt;li&gt;Fast queries, because the engine only needs one hop from dimension to fact.&lt;/li&gt;
&lt;li&gt;Short, readable DAX.&lt;/li&gt;
&lt;li&gt;Easy for report builders to understand, since dimensions are clearly labelled.&lt;/li&gt;
&lt;li&gt;Works well with time intelligence through a dedicated date table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some redundancy inside dimensions (for example a Category repeated on each product).&lt;/li&gt;
&lt;li&gt;Requires upfront design and data preparation in Power Query or the source.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When it is appropriate:&lt;/strong&gt; Almost all business intelligence models: sales, finance, HR, operations, marketing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance and complexity:&lt;/strong&gt; Excellent performance. VertiPaq compresses dimension columns well, and the fact table stays narrow because it holds mostly keys and numbers. Complexity is low to moderate.&lt;/p&gt;

&lt;h4&gt;
  
  
  1.3 Snowflake schema
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; A snowflake schema is a star schema where dimensions are &lt;strong&gt;normalised&lt;/strong&gt; into further related tables. A dimension connects to other dimensions rather than only to the fact table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure:&lt;/strong&gt; For example, &lt;code&gt;DimProduct&lt;/code&gt; links to &lt;code&gt;DimProductSubcategory&lt;/code&gt;, which links to &lt;code&gt;DimProductCategory&lt;/code&gt;. Similarly &lt;code&gt;DimLocation&lt;/code&gt; links to &lt;code&gt;DimRegion&lt;/code&gt;, then to &lt;code&gt;DimCountry&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;erDiagram
    DimProductCategory ||--o{ DimProductSubcategory : "CategoryID"
    DimProductSubcategory ||--o{ DimProduct : "SubcategoryID"
    DimProduct ||--o{ FactSales : "ProductID"
    DimCountry ||--o{ DimRegion : "CountryID"
    DimRegion ||--o{ DimLocation : "RegionID"
    DimLocation ||--o{ FactSales : "LocationID"
    DimDate ||--o{ FactSales : "DateKey"

    FactSales {
        int SalesID PK
        int ProductID FK
        int LocationID FK
        int DateKey FK
        int Quantity
        decimal SalesAmount
    }&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less redundancy in dimensions.&lt;/li&gt;
&lt;li&gt;Mirrors how many transactional databases are already structured.&lt;/li&gt;
&lt;li&gt;Changes to a higher level (for example a category name) happen in one table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More tables and more relationships to maintain.&lt;/li&gt;
&lt;li&gt;Filters must travel through several hops, which adds complexity and can slow queries.&lt;/li&gt;
&lt;li&gt;Harder for report authors to navigate, since a single business concept is split across many tables.&lt;/li&gt;
&lt;li&gt;Usually saves very little space in Power BI, because dimensions are small compared with facts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When it is appropriate:&lt;/strong&gt; When a dimension is very large and a sub-dimension is shared by several other tables, or when you are modelling directly on top of a normalised source and cannot reshape it. Even then, I usually flatten the dimension in Power Query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance and complexity:&lt;/strong&gt; Slightly slower and noticeably more complex than a star schema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Flat table&lt;/th&gt;
&lt;th&gt;Star schema&lt;/th&gt;
&lt;th&gt;Snowflake schema&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Number of tables&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1 fact + several dimensions&lt;/td&gt;
&lt;td&gt;1 fact + dimensions + sub-dimensions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redundancy&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low to moderate&lt;/td&gt;
&lt;td&gt;Lowest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query speed&lt;/td&gt;
&lt;td&gt;Slows as data grows&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Slightly slower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DAX simplicity&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ease of use&lt;/td&gt;
&lt;td&gt;Easy at first&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Harder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Small, one-off analysis&lt;/td&gt;
&lt;td&gt;Most BI projects&lt;/td&gt;
&lt;td&gt;Normalised sources, shared sub-dimensions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;h3&gt;
  
  
  Fact tables
&lt;/h3&gt;

&lt;p&gt;A fact table records &lt;strong&gt;business events or transactions&lt;/strong&gt;. It usually stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Numeric measures&lt;/strong&gt; you want to aggregate: &lt;code&gt;SalesAmount&lt;/code&gt;, &lt;code&gt;Quantity&lt;/code&gt;, &lt;code&gt;DiscountAmount&lt;/code&gt;, &lt;code&gt;Cost&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foreign keys&lt;/strong&gt; pointing to dimension tables: &lt;code&gt;CustomerID&lt;/code&gt;, &lt;code&gt;ProductID&lt;/code&gt;, &lt;code&gt;DateKey&lt;/code&gt;, &lt;code&gt;LocationID&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sometimes a transaction identifier such as &lt;code&gt;OrderID&lt;/code&gt; or &lt;code&gt;InvoiceNumber&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fact tables are typically long (many rows) and narrow (few columns). Common examples are &lt;code&gt;FactSales&lt;/code&gt;, &lt;code&gt;FactOrders&lt;/code&gt; and &lt;code&gt;FactTransactions&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dimension tables
&lt;/h3&gt;

&lt;p&gt;A dimension table stores &lt;strong&gt;descriptive attributes&lt;/strong&gt;, the "who, what, where, when" used to slice and filter the facts. Each dimension has a unique key.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DimCustomer&lt;/code&gt;: CustomerID, name, segment, join date.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DimProduct&lt;/code&gt;: ProductID, product name, category, brand, unit price.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DimDate&lt;/code&gt;: date, year, quarter, month, weekday, fiscal period.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DimLocation&lt;/code&gt;: LocationID, city, region, country.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dimensions are typically short (fewer rows) and wide (many descriptive columns).&lt;/p&gt;

&lt;h3&gt;
  
  
  Measures versus attributes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Numeric business events (facts)&lt;/th&gt;
&lt;th&gt;Descriptive attributes (dimensions)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SalesAmount, Quantity, Cost&lt;/td&gt;
&lt;td&gt;Customer name, product category, city&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Added up, averaged, counted&lt;/td&gt;
&lt;td&gt;Used for grouping, filtering and labels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Changes with every transaction&lt;/td&gt;
&lt;td&gt;Changes rarely&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Grain (granularity)
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;grain&lt;/strong&gt; is what one row of the fact table represents. It is the most important decision in the design, and you should state it in a single sentence.&lt;/p&gt;

&lt;p&gt;For example: &lt;em&gt;"One row in FactSales represents one product sold on one order line."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If the grain is one line per order line, you can answer questions by product, customer, day or store. If the grain were one row per month per store, you could no longer report by product or by day. A rule I follow: keep the grain as detailed as the business will ever need, and never mix different grains in the same fact table.&lt;/p&gt;

&lt;h3&gt;
  
  
  A practical example
&lt;/h3&gt;

&lt;p&gt;Imagine a retail company. Every time a product is sold, a row is added to &lt;code&gt;FactSales&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FactSales&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SalesID&lt;/th&gt;
&lt;th&gt;DateKey&lt;/th&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;ProductID&lt;/th&gt;
&lt;th&gt;LocationID&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;SalesAmount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;20260901&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;20260901&lt;/td&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;7,200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;20260902&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;21,600&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;DimCustomer&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;CustomerName&lt;/th&gt;
&lt;th&gt;Segment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;Retail&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;Corporate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The fact table is connected to &lt;code&gt;DimCustomer&lt;/code&gt;, &lt;code&gt;DimProduct&lt;/code&gt;, &lt;code&gt;DimDate&lt;/code&gt; and &lt;code&gt;DimLocation&lt;/code&gt;, exactly as in the star schema diagram in section 1.2. A user can now pick "Corporate" in a slicer, and the total in a card visual changes to include only Brian's sales, without ever storing the segment in &lt;code&gt;FactSales&lt;/code&gt;.&lt;/p&gt;




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

&lt;h3&gt;
  
  
  What is a relationship?
&lt;/h3&gt;

&lt;p&gt;A relationship links two tables through a shared column, so that filters applied to one table affect the other. Relationships are necessary because, in a good model, data is &lt;strong&gt;split across multiple tables&lt;/strong&gt;. Without relationships, selecting "Electronics" in a product slicer would do nothing to the sales table, because Power BI would not know how the two are connected.&lt;/p&gt;

&lt;p&gt;Importantly, a relationship does &lt;strong&gt;not&lt;/strong&gt; merge the tables or copy any data. It only tells the engine how to propagate filters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key concepts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary key:&lt;/strong&gt; A column that uniquely identifies each row in a table (for example &lt;code&gt;CustomerID&lt;/code&gt; in &lt;code&gt;DimCustomer&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foreign key:&lt;/strong&gt; A column in another table that refers to a primary key (for example &lt;code&gt;CustomerID&lt;/code&gt; in &lt;code&gt;FactSales&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unique values:&lt;/strong&gt; The "one" side of a relationship must contain unique, non-blank values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cardinality:&lt;/strong&gt; Describes how many matching rows exist on each side of a relationship.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referential integrity:&lt;/strong&gt; Every foreign key value in the fact table should have a matching key in the dimension. When it does not, Power BI shows a &lt;code&gt;(Blank)&lt;/code&gt; group in visuals for those unmatched rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active and inactive relationships:&lt;/strong&gt; Only one relationship between two tables can be active at a time. Inactive relationships appear as dashed lines and are used only when a DAX measure calls &lt;code&gt;USERELATIONSHIP&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why CustomerID is unique in one table and repeated in another:&lt;/strong&gt; In &lt;code&gt;DimCustomer&lt;/code&gt;, &lt;code&gt;CustomerID&lt;/code&gt; appears once because each customer is a single record. In &lt;code&gt;FactSales&lt;/code&gt;, the same &lt;code&gt;CustomerID&lt;/code&gt; appears as many times as that customer made purchases. Customer 101 is one row in the dimension but might appear in fifty sales rows. That is the classic &lt;strong&gt;one-to-many&lt;/strong&gt; relationship.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 One-to-many (1:*)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; One row in the "one" table matches many rows in the "many" table. The one side must have unique values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; &lt;code&gt;DimProduct&lt;/code&gt; (one) to &lt;code&gt;FactSales&lt;/code&gt; (many). One product can appear on thousands of sales rows.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;erDiagram
    DimProduct ||--o{ FactSales : "1 to many"&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; This is the default and the workhorse of Power BI models. Use it between every dimension and its fact table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When not to use:&lt;/strong&gt; It cannot be used when the "one" column contains duplicates. Fix the data or reconsider the design.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Each row in one table matches at most one row in the other, and both columns are unique.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; &lt;code&gt;DimCustomer&lt;/code&gt; and &lt;code&gt;DimCustomerProfile&lt;/code&gt;, where the profile table stores extra details such as birthday and preferences.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;erDiagram
    DimCustomer ||--|| DimCustomerProfile : "1 to 1"&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Rarely. It can be used when one table is split for security or source reasons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When not to use:&lt;/strong&gt; In most cases, a one-to-one relationship suggests the two tables should be merged into one in Power Query, which simplifies the model.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Many-to-many (&lt;em&gt;:&lt;/em&gt;)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Neither column has unique values, so many rows on each side can match. Power BI lets you create this cardinality directly, but results can be ambiguous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; A &lt;code&gt;SalesTargets&lt;/code&gt; table with one target per region per month, related to &lt;code&gt;FactSales&lt;/code&gt; on &lt;code&gt;Region&lt;/code&gt;. Region repeats on both sides.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;erDiagram
    FactSales }o--o{ SalesTargets : "Region (many to many)"&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Only when a bridge table is not practical, or when relating two fact tables at different grains as a last resort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When not to use:&lt;/strong&gt; As a habit. The better fix is almost always to add a shared dimension (here, &lt;code&gt;DimRegion&lt;/code&gt;) and relate both tables to it with one-to-many relationships, which gives a proper star schema.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Screenshot placeholder:&lt;/strong&gt; Insert your own Model view screenshot showing the three cardinalities with the 1, * and relationship lines visible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Active and inactive relationships
&lt;/h3&gt;

&lt;p&gt;A common case is &lt;strong&gt;role-playing dates&lt;/strong&gt;. &lt;code&gt;FactSales&lt;/code&gt; has both &lt;code&gt;OrderDate&lt;/code&gt; and &lt;code&gt;ShipDate&lt;/code&gt;, and both link to &lt;code&gt;DimDate&lt;/code&gt;. Only one can be active (say &lt;code&gt;OrderDate&lt;/code&gt;). The other stays inactive and is used in a measure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sales by Ship Date =
CALCULATE(
    [Total Sales],
    USERELATIONSHIP(FactSales[ShipDate], DimDate[Date])
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;h3&gt;
  
  
  How filters propagate
&lt;/h3&gt;

&lt;p&gt;Filter direction defines which way filters travel across a relationship. In a well-designed model, filters flow from the "one" side to the "many" side, in other words from dimensions to facts.&lt;/p&gt;

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

&lt;p&gt;With single direction, a filter on the dimension affects the fact table, but a filter on the fact table does not affect the dimension.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; A user selects "Laptops" in a slicer built from &lt;code&gt;DimProduct[Category]&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The filter is applied to &lt;code&gt;DimProduct&lt;/code&gt;, keeping only laptop products.&lt;/li&gt;
&lt;li&gt;It travels along the relationship to &lt;code&gt;FactSales&lt;/code&gt;, keeping only sales rows for those products.&lt;/li&gt;
&lt;li&gt;Any visual that sums &lt;code&gt;FactSales[SalesAmount]&lt;/code&gt; now shows laptop sales only.
&lt;/li&gt;
&lt;/ol&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    A["DimProduct&amp;lt;br/&amp;gt;Category = Laptops"] --&amp;gt;|filter flows| B["FactSales&amp;lt;br/&amp;gt;only laptop rows"]&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;
  
  
  Both (bidirectional) filtering
&lt;/h3&gt;

&lt;p&gt;With Both, filters travel in both directions. A selection on the fact table can also filter the dimension.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it can help:&lt;/strong&gt; Filtering a slicer so it only shows dimension values that actually have sales, or handling certain many-to-many scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why bidirectional filtering needs care
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ambiguous filter paths:&lt;/strong&gt; If two dimensions are connected to each other through the fact table and both are bidirectional, Power BI may not know which path to use, and results can be wrong or the relationship can be blocked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unexpected results:&lt;/strong&gt; Filters spread through the model in ways report users do not expect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; More filter propagation means more work for the engine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unnecessary complexity:&lt;/strong&gt; Models become harder to reason about and debug.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My rule is to keep everything single-direction by default. When I need a filter to work in the reverse direction, I try a DAX measure first (for example using &lt;code&gt;CROSSFILTER&lt;/code&gt; inside &lt;code&gt;CALCULATE&lt;/code&gt;), and only turn on Both for a specific, well-understood reason.&lt;/p&gt;




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

&lt;h3&gt;
  
  
  What is a join?
&lt;/h3&gt;

&lt;p&gt;A join combines rows from two tables based on a matching column. In Power Query, this is done with &lt;strong&gt;Home &amp;gt; Merge Queries&lt;/strong&gt; (or &lt;em&gt;Merge Queries as New&lt;/em&gt;). You choose two tables, select the matching column in each, and pick a &lt;strong&gt;join kind&lt;/strong&gt;. Power Query then adds a column of nested tables, which you expand to bring in the columns you need.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Screenshot placeholder:&lt;/strong&gt; Insert your own screenshot of the Merge dialog, showing both tables, the matching columns and the Join Kind dropdown.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Example data
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Customers&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C2&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C3&lt;/td&gt;
&lt;td&gt;Chloe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C4&lt;/td&gt;
&lt;td&gt;David&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Orders&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;O101&lt;/td&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O102&lt;/td&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;2,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O103&lt;/td&gt;
&lt;td&gt;C2&lt;/td&gt;
&lt;td&gt;7,200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O104&lt;/td&gt;
&lt;td&gt;C5&lt;/td&gt;
&lt;td&gt;1,800&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Customers is the &lt;strong&gt;first (left)&lt;/strong&gt; table and Orders is the &lt;strong&gt;second (right)&lt;/strong&gt; table. Note that Chloe and David have no orders, and order O104 belongs to a customer (C5) who does not exist in Customers.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Keeps &lt;strong&gt;all rows from the left table&lt;/strong&gt; and only the matching rows from the right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Records retained:&lt;/strong&gt; All customers, with order details where they exist. Unmatched customers get null values.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O101&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O102&lt;/td&gt;
&lt;td&gt;2,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C2&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;O103&lt;/td&gt;
&lt;td&gt;7,200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C3&lt;/td&gt;
&lt;td&gt;Chloe&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C4&lt;/td&gt;
&lt;td&gt;David&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use it for:&lt;/strong&gt; Listing every customer and their orders, including customers who have not bought anything. It is the most common join.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Keeps &lt;strong&gt;all rows from the right table&lt;/strong&gt; and only matching rows from the left.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Records retained:&lt;/strong&gt; All orders, with customer details where they exist.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O101&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O102&lt;/td&gt;
&lt;td&gt;2,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C2&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;O103&lt;/td&gt;
&lt;td&gt;7,200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C5&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;O104&lt;/td&gt;
&lt;td&gt;1,800&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use it for:&lt;/strong&gt; Making sure no orders are lost, and spotting orders that have no matching customer record.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Keeps &lt;strong&gt;all rows from both tables&lt;/strong&gt;, matching where possible and filling with nulls where not.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O101&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O102&lt;/td&gt;
&lt;td&gt;2,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C2&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;O103&lt;/td&gt;
&lt;td&gt;7,200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C3&lt;/td&gt;
&lt;td&gt;Chloe&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C4&lt;/td&gt;
&lt;td&gt;David&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C5&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;O104&lt;/td&gt;
&lt;td&gt;1,800&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use it for:&lt;/strong&gt; Reconciling two sources and seeing everything that matches and everything that does not.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Keeps &lt;strong&gt;only rows that match in both tables&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O101&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O102&lt;/td&gt;
&lt;td&gt;2,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C2&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;O103&lt;/td&gt;
&lt;td&gt;7,200&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use it for:&lt;/strong&gt; Analysing only customers who have placed orders. Be careful, because it silently drops unmatched rows.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Keeps &lt;strong&gt;only rows from the left table that have no match&lt;/strong&gt; in the right.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C3&lt;/td&gt;
&lt;td&gt;Chloe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C4&lt;/td&gt;
&lt;td&gt;David&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use it for:&lt;/strong&gt; Finding customers who never ordered, products that never sold, or employees with no assigned department.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.6 Right Anti Join
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Keeps &lt;strong&gt;only rows from the right table that have no match&lt;/strong&gt; in the left.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;O104&lt;/td&gt;
&lt;td&gt;C5&lt;/td&gt;
&lt;td&gt;1,800&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use it for:&lt;/strong&gt; Finding orphan records, such as orders whose customer is missing. It is a very useful data quality check before creating relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Join kind&lt;/th&gt;
&lt;th&gt;Rows kept&lt;/th&gt;
&lt;th&gt;Result rows (this example)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Left Outer&lt;/td&gt;
&lt;td&gt;All left + matching right&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Right Outer&lt;/td&gt;
&lt;td&gt;All right + matching left&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full Outer&lt;/td&gt;
&lt;td&gt;All rows from both&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inner&lt;/td&gt;
&lt;td&gt;Only matching rows&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Left Anti&lt;/td&gt;
&lt;td&gt;Left rows with no match&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Right Anti&lt;/td&gt;
&lt;td&gt;Right rows with no match&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  6. Power Query Joins vs Power BI Relationships
&lt;/h2&gt;

&lt;p&gt;Both connect tables, but they are very different operations.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Power Query merge (join)&lt;/th&gt;
&lt;th&gt;Model relationship&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What it does&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Physically combines columns and rows into a result table&lt;/td&gt;
&lt;td&gt;Links tables logically, without combining them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;When it happens&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;During data loading and transformation, at each refresh&lt;/td&gt;
&lt;td&gt;In the data model, at query time when a visual is used&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A new or wider table&lt;/td&gt;
&lt;td&gt;Tables stay separate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data duplicated?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes, values are repeated on each row&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fixed once loaded&lt;/td&gt;
&lt;td&gt;Filters are dynamic and respond to slicers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Does a merge physically combine data?&lt;/strong&gt; Yes. The columns from the second table are added into the result, and the merged data is stored as one table when it loads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does creating a relationship combine the tables?&lt;/strong&gt; No. The tables remain separate. Power BI just uses the relationship to pass filters between them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At what stage does each occur?&lt;/strong&gt; Merges happen in Power Query, the transformation stage, before data is loaded. Relationships are created in the model stage, after loading, and are evaluated while reports run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When would I choose a merge?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To flatten a snowflaked dimension into one dimension table (for example, joining product, subcategory and category).&lt;/li&gt;
&lt;li&gt;To bring a lookup column into a table when it is truly one-to-one.&lt;/li&gt;
&lt;li&gt;To do data quality checks with anti joins.&lt;/li&gt;
&lt;li&gt;To clean and reshape data before loading it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How can excessive merging hurt a model?&lt;/strong&gt; Merging everything into one giant table recreates the flat table problem: heavy redundancy, bigger file size, slower refresh, harder maintenance, and difficulty adding new data sources. It also mixes grains, which leads to double counting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why keep facts and dimensions separate?&lt;/strong&gt; Separate tables keep the fact table narrow and the descriptive data stored once. Filters stay clean, DAX stays simple, updates are made in one place, and the model can grow with new fact tables that share the same dimensions (for example &lt;code&gt;FactSales&lt;/code&gt; and &lt;code&gt;FactBudget&lt;/code&gt; both using &lt;code&gt;DimDate&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; If I merge &lt;code&gt;DimCustomer&lt;/code&gt; into &lt;code&gt;FactSales&lt;/code&gt;, customer name and segment are copied onto every sales row, and a new customer attribute requires reloading the full fact table. If I keep them separate and use a relationship, &lt;code&gt;DimCustomer&lt;/code&gt; is stored once and I can add an attribute there without touching the fact table.&lt;/p&gt;




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

&lt;p&gt;For a typical business intelligence project, I would use a &lt;strong&gt;star schema&lt;/strong&gt;, with one-to-many relationships and single-direction filters from dimensions to facts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why a star schema
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Narrow fact tables, small dimensions and one-hop filters compress well and scan quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DAX simplicity:&lt;/strong&gt; Measures such as &lt;code&gt;SUM(FactSales[SalesAmount])&lt;/code&gt; work with natural filter context, with no need for complex filter overrides.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readability:&lt;/strong&gt; Anyone opening the model can see what the facts are and how they can be sliced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; New facts (budgets, returns) can be added and connected to the same shared dimensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low redundancy:&lt;/strong&gt; Descriptive data is stored once, in dimensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability:&lt;/strong&gt; Changes happen in one place, and the structure is well known to other BI developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of report building:&lt;/strong&gt; Report authors pick fields from clearly named dimension tables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter propagation:&lt;/strong&gt; Filters follow one predictable path, dimension to fact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why not the alternatives
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flat table:&lt;/strong&gt; Fine for small, one-off work, but it does not scale and it makes DAX and maintenance harder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake:&lt;/strong&gt; Adds hops and tables for little benefit in Power BI. If the source is snowflaked, I flatten the dimensions in Power Query.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Relationship design I would implement
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cardinality:&lt;/strong&gt; One-to-many from each dimension to the fact table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter direction:&lt;/strong&gt; Single, from dimension to fact, by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bidirectional filtering:&lt;/strong&gt; Avoided unless there is a specific, tested reason.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date table:&lt;/strong&gt; A dedicated &lt;code&gt;DimDate&lt;/code&gt;, marked as the date table, with an active relationship on the main date and inactive relationships for others, activated with &lt;code&gt;USERELATIONSHIP&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keys:&lt;/strong&gt; Integer surrogate keys where possible, unique and non-blank on the dimension side.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrity checks:&lt;/strong&gt; Anti joins in Power Query to find fact rows with no matching dimension row before loading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden fields:&lt;/strong&gt; Foreign keys in the fact table are hidden from report view so authors use dimension fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Many-to-many:&lt;/strong&gt; Avoided by introducing shared dimensions or bridge tables.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Good Power BI models are not complicated, they are deliberate. Use Power Query to clean, reshape and check the data, use a star schema to organise it, and use simple one-to-many relationships with single-direction filters to connect it. When something goes wrong in a report, start by checking the grain of your fact table, the uniqueness of your dimension keys, and the direction of your filters. Most modelling problems are found in one of those three places.&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>data</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Amazing</title>
      <dc:creator>SAMWEL SHIHANDE</dc:creator>
      <pubDate>Sun, 23 Aug 2026 01:13:15 +0000</pubDate>
      <link>https://dev.to/samwel_shihande_3b29d4559/amazing-b7g</link>
      <guid>https://dev.to/samwel_shihande_3b29d4559/amazing-b7g</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/samwel_shihande_3b29d4559/my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-4ifh" class="crayons-story__hidden-navigation-link"&gt;My First GitHub Project: From A Local Folder To GitHub Using Git And SSH&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/samwel_shihande_3b29d4559" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F4071724%2F68bb44ce-bddb-4d72-b75a-74ebcafb45eb.jpg" alt="samwel_shihande_3b29d4559 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/samwel_shihande_3b29d4559" class="crayons-story__secondary fw-medium m:hidden"&gt;
              SAMWEL SHIHANDE
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                SAMWEL SHIHANDE
                
                
              
              &lt;div id="story-author-preview-content-4464889" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/samwel_shihande_3b29d4559" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F4071724%2F68bb44ce-bddb-4d72-b75a-74ebcafb45eb.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;SAMWEL SHIHANDE&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/samwel_shihande_3b29d4559/my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-4ifh" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 23&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/samwel_shihande_3b29d4559/my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-4ifh" id="article-link-4464889"&gt;
          My First GitHub Project: From A Local Folder To GitHub Using Git And SSH
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/area"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;area&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mechanics"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mechanics&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/whisper"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;whisper&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/svelte"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;svelte&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/samwel_shihande_3b29d4559/my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-4ifh" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/samwel_shihande_3b29d4559/my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-4ifh#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>My First GitHub Project: From A Local Folder To GitHub Using Git And SSH</title>
      <dc:creator>SAMWEL SHIHANDE</dc:creator>
      <pubDate>Sun, 23 Aug 2026 01:02:57 +0000</pubDate>
      <link>https://dev.to/samwel_shihande_3b29d4559/my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-4ifh</link>
      <guid>https://dev.to/samwel_shihande_3b29d4559/my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-4ifh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction.
&lt;/h2&gt;

&lt;p&gt;I have folder with files sitting quietly on my laptop, and the idea of turning it into a "real project" on github feels like a mountain. This week, i climbed that mountain and i want to walk you through exactly how i did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git vs GitHub.
&lt;/h2&gt;

&lt;p&gt;Git is a tool that lives on my computer and its the thing that actually tracks the changes i make to my files&lt;br&gt;
GitHub is a website. Its where i can store a copy of that diary online so i can share it with other people, back it up or work on it from a different computer. Git does the tracking and GitHub does the hosting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Creating the folder.
&lt;/h2&gt;

&lt;p&gt;Using Git Bash, i first create a folder called &lt;strong&gt;&lt;em&gt;my-first-project&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;
Git Bash is a command-line tool that allows users to interact with Git and perfom common computer tasks using commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git Bash folder commands
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;ls&lt;/em&gt; -view the files and folders&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;mkdir&lt;/em&gt; -create a new folder&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;_cd _-Enter the folder&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;cd ..&lt;/em&gt; -Go back one folder&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Turning my local folder into a Git project
&lt;/h2&gt;

&lt;p&gt;To make Git start paying attention to _&lt;em&gt;my-first-project&lt;/em&gt;, i opened my terminal, navigate into the folder and run the commands above.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Setting up SSH so GitHub actually trusts me.
&lt;/h2&gt;

&lt;p&gt;This part is what made me feel like a real developer for the first time. Think of SSH key like a digital handshake. My computer has one half of the key and GitHub has the other half key and they recognize each other without me typing password every single time.&lt;br&gt;
Here's how i set mine up:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate the key on my machine&lt;br&gt;
I use the command-line &lt;strong&gt;&lt;em&gt;ssh-keygen -T ed25519 -C "&lt;a href="mailto:sshihande@gmail.com"&gt;sshihande@gmail.com&lt;/a&gt;"&lt;/em&gt;&lt;/strong&gt; on Git Bash.&lt;br&gt;
This creates two files, a private key and a public key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the public key:&lt;br&gt;
I use the command-line cat_which is used to copy the public key.&lt;br&gt;
To print the public key in my terminal i use the run:&lt;strong&gt;_ cat ~/.ssh/id_ed25519.pub&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add it to GitHub:&lt;br&gt;
I logged into GitHub and pasted it in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tested the connection:&lt;br&gt;
I ran _&lt;strong&gt;ssh -T &lt;a href="mailto:git@github.com"&gt;git@github.com&lt;/a&gt;&lt;/strong&gt;_to test the connection. The first time it warned me about connecting to a new host  and asked me if i wanted to continue, i typed &lt;strong&gt;yes&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: creating the Repository on GitHub
&lt;/h2&gt;

&lt;p&gt;On GitHub i clicked new repository, gave it the same name as my local folder and this part matters.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4: Connecting my local folder to that repository
&lt;/h2&gt;

&lt;p&gt;I think of &lt;strong&gt;origin&lt;/strong&gt; as just a nickname Git uses to refer to that GitHub repository so i dont have totype the full url every time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: The actual workflow. Staging, committing and pushing.
&lt;/h2&gt;

&lt;p&gt;This is the part of Git that took me a while to really get, so let me break iTt down the way i finally understood it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Working directory -This is just my folder as it exists right now, with all my raw changes, Git sees that something changed but hasn't been told to care about it yet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Staging Area -This is like a waiting room. I choose exactly which changes i want to include in my next save point. I do this with Git Bash.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit -This is the actual &lt;strong&gt;save point&lt;/strong&gt; in the projects history. I learnt that a commit message should actually describe what changed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Push -This is where my local commit atually travels up to GitHub.&lt;/p&gt;
&lt;h2&gt;
  
  
  What i actually learnt from doing all this.
&lt;/h2&gt;

&lt;p&gt;If you are about to do this for the first time dont rush past the ssh set-up.It was intimidating at first bur i ended up enjoying .&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>area</category>
      <category>mechanics</category>
      <category>whisper</category>
      <category>svelte</category>
    </item>
  </channel>
</rss>
