Mysql

LEFT JOIN only first row

27 September 2026 · 5 min read

LEFT JOIN only first row

Navigating complex database relationships is a core skill for any data professional, and a common challenge arises when you need to retrieve data from a related table but only for the very first matching entry. While a standard LEFT JOIN operation typically returns all matching rows from the joined table, there are many scenarios where you specifically need to implement a LEFT JOIN only first row. This requirement often emerges when dealing with one-to-many relationships, such as customers with multiple orders, products with various price points, or users with several login attempts, but you only care about the earliest, latest, or otherwise “first” relevant record. Understanding how to achieve this efficiently is crucial for accurate reporting, streamlined data processing, and optimizing your SQL queries.

Understanding the “First Row” Challenge in SQL Joins

The standard behavior of a LEFT JOIN is to return all rows from the left table and all matching rows from the right table. If there are multiple matches in the right table for a single row in the left table, the left table’s row will be duplicated for each match. For instance, if you have a Customers table and an Orders table, and a customer has five orders, a simple LEFT JOIN will present that customer’s information five times, once for each order. This duplication is often undesirable when you only need to link to one specific order, such as their initial purchase or their most recent one.

Defining what constitutes the “first” row is paramount. Is it the row with the lowest ID, the earliest timestamp, or perhaps the smallest numerical value in a particular column? Without a clear criterion for ordering, the concept of “first” is ambiguous in a relational database. Once defined, the challenge then becomes how to apply this “first” filter before or during the join operation to prevent unnecessary data duplication and ensure optimal performance, especially with large datasets. Incorrectly handling this can lead to bloated result sets, slower query execution, and potentially inaccurate analytical outcomes.

Method 1: Leveraging Correlated Subqueries

One straightforward way to achieve a LEFT JOIN only first row is by employing a correlated subquery within your SELECT or WHERE clause, or more commonly, as part of a derived table or Common Table Expression (CTE). A correlated subquery executes once for each row processed by the outer query, allowing it to reference columns from the outer query. This method is often intuitive for those new to more advanced SQL concepts, as it directly expresses the “get the first for this row” logic.

While conceptually simple, the performance of correlated subqueries can degrade significantly on very large datasets due to their row-by-row execution nature. However, for smaller tables or specific scenarios where readability outweighs marginal performance gains, they remain a valid and understandable option. The key is to ensure the subquery correctly identifies and returns only the single desired “first” row based on your ordering criteria. For instance, you might select the minimum order ID for each customer directly within the subquery.

SELECT c.CustomerID, c.CustomerName, o.OrderID, o.OrderDate, o.TotalAmount FROM Customers c LEFT JOIN (SELECT o1.OrderID, o1.CustomerID, o1.OrderDate, o1.TotalAmount FROM Orders o1 WHERE o1.OrderID = (SELECT MIN(o2.OrderID) FROM Orders o2 WHERE o2.CustomerID = o1.CustomerID) ) o ON c.CustomerID = o.CustomerID; 

This approach defines the “first” order by the minimum OrderID for each distinct CustomerID, ensuring that the join only ever links to that single, earliest order. It’s a clear example of how a correlated subquery helps to filter for the desired single row before the main join is completed.

Method 2: Utilizing Window Functions (ROW_NUMBER(), RANK())

For scenarios requiring a LEFT JOIN only first row, especially when dealing with large datasets or complex “first row” definitions, window functions like ROW_NUMBER() offer a powerful and highly performant solution. ROW_NUMBER() assigns a unique, sequential integer to rows within a specified partition of a result set, based on the logical order of rows in that partition. This allows you to precisely identify the first (or Nth) row for each group.

The typical pattern involves partitioning your data by the join key (e.g., CustomerID) and then ordering it by your “first row” criterion (e.g., OrderDate ASC). By assigning row numbers within each partition, you can then easily filter for ROW_NUMBER() = 1 in a subquery or CTE before performing the final LEFT JOIN. This method is generally preferred for its efficiency and flexibility, as it processes the entire dataset once to assign row numbers, then filters, rather than executing a subquery for every row. Question & Answer :

I read many threads about getting only the first row of a left join, but, for some reason, this does not work for me.

Here is my structure (simplified of course)

Feeds

id | title | content ---------------------- 1 | Feed 1 | ... 

Artists

artist_id | artist_name ----------------------- 1 | Artist 1 2 | Artist 2 

feeds_artists

rel_id | artist_id | feed_id ---------------------------- 1 | 1 | 1 2 | 2 | 1 ... 

Now i want to get the articles and join only the first Artist and I thought of something like this:

SELECT * FROM feeds LEFT JOIN feeds_artists ON wp_feeds.id = ( SELECT feeds_artists.feed_id FROM feeds_artists WHERE feeds_artists.feed_id = feeds.id LIMIT 1 ) WHERE feeds.id = '13815' 

just to get only the first row of the feeds_artists, but already this does not work.

I can not use TOP because of my database and I can’t group the results by feeds_artists.artist_id as i need to sort them by date (I got results by grouping them this way, but the results where not the newest)

Tried something with OUTER APPLY as well - no success as well. To be honest i can not really imagine whats going on in those rows - probably the biggest reason why i cant get this to work.

SOLUTION:

SELECT * FROM feeds f LEFT JOIN artists a ON a.artist_id = ( SELECT artist_id FROM feeds_artists fa WHERE fa.feed_id = f.id LIMIT 1 ) WHERE f.id = '13815' 

If you can assume that artist IDs increment over time, then the MIN(artist_id) will be the earliest.

So try something like this:

SELECT * FROM feeds f LEFT JOIN artists a ON a.artist_id = ( SELECT MIN(fa.artist_id) a_id FROM feeds_artists fa WHERE fa.feed_id = f.feed_id )