Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limit results from joined table to one row

Tags:

sql

mysql

Here is a simplified table structure:

TABLE products (
 product_id INT (primary key, auto_increment),
 category_id INT,
 product_title VARCHAR,
 etc
);

TABLE product_photos (
 product_photo_id (primary key, auto_increment),
 product_id INT,
 photo_href VARCHAR,
 photo_order INT
);

A product can have multiple photos, the first product photo for each product (based on the photo_order) is the default photo.

Now, I only need all of the photos on the product details page, but on pages where I am listing multiple products, for example a product directory page, I only want to display the default photo.

So what I am trying to do, is query a list of products including the default photo for each product.

This obviously doesn't work, it will return all photos with the product info duplicated for each photo:

SELECT p.*, ph.*
FROM products AS p
LEFT JOIN product_photos AS ph
ON p.product_id=ph.product_id
ORDER BY p.product_title ASC

I need to figure out how to do something like this, but I don't know the syntax (or if it is possible)

SELECT p.*, ph.*
FROM products AS p
LEFT JOIN product_photos AS ph
    ON p.product_id=ph.product_id  **ORDER BY ph.photo_order ASC LIMIT 1**
ORDER BY p.product_title ASC

Edit: I figured out a solution with help from the answers below, thanks all!

SELECT p.*, ph.*
FROM products AS p
LEFT JOIN product_photos AS ph 
    ON p.product_id=ph.product_id
    AND ph.photo_order =
    (
        SELECT MIN(z.photo_order)
        FROM product_photos AS z
        WHERE z.product_id=p.product_id
    )
GROUP BY p.product_id
ORDER BY p.product_title ASC
like image 859
Rob Avatar asked Jun 05 '10 01:06

Rob


People also ask

How do I return only one row in SQL?

To return only the first row that matches your SELECT query, you need to add the LIMIT clause to your SELECT statement. The LIMIT clause is used to control the number of rows returned by your query. When you add LIMIT 1 to the SELECT statement, then only one row will be returned.

Can we use LIMIT with group by in SQL?

No, you can't LIMIT subqueries arbitrarily (you can do it to a limited extent in newer MySQLs, but not for 5 results per group). This is a groupwise-maximum type query, which is not trivial to do in SQL.

How do you reduce left join in SQL Server?

WITH myquery AS ( SELECT * FROM TEST_FILE1 ) , a as ( select col1, col2, 42 as col3, col4, col5 from ( (select distinct col1 from myquery) cross join (select distinct col2 from myquery) cross join (select distinct col4 from myquery) cross join (select distinct col5 from myquery) ) ) select a.

How can I get the first row of multiple rows in SQL?

To do that, you can use the ROW_NUMBER() function. In OVER() , you specify the groups into which the rows should be divided ( PARTITION BY ) and the order in which the numbers should be assigned to the rows ( ORDER BY ).


3 Answers

SELECT p.*, ph.*
FROM products AS p
INNER JOIN product_photos AS ph
    ON p.product_id = ph.product_id
LEFT JOIN product_photos AS ph2
    ON p.product_id = ph2.product_id
    AND ph2.photo_order < ph.photo_order
WHERE ph2.photo_order IS NULL
ORDER BY p.product_title ASC

Note the how it joins to the product_photos table twice. The WHERE ph2.photo_order IS NULL will throw out all but the lowest photo order. It won't protect you against duplicate product_id / photo_orders combo though, you could add a GROUP BY on p.id if that's the case.

like image 63
Wrikken Avatar answered Oct 08 '22 08:10

Wrikken


Use:

SELECT p.*,
       pp.*
  FROM PRODUCTS p
  JOIN PRODUCT_PHOTOS pp ON pp.product_id = p.product_id
  JOIN (SELECT x.product_id,
               MIN(x.photo_order) AS default_photo
          FROM PRODUCT_PHOTOS x
      GROUP BY x.product_id) y ON y.product_id = pp.product_id
                              AND y.default_photo  = pp.photo_order
like image 15
OMG Ponies Avatar answered Oct 08 '22 09:10

OMG Ponies


    SELECT p.*, ph.*
    FROM products AS p
    LEFT JOIN product_photos AS ph ON p.product_id=ph.product_id
    ORDER BY p.product_title ASC, ph.photo_order ASC
    GROUP BY p.product_id
    LIMIT 0,10
like image 3
Kovge Avatar answered Oct 08 '22 07:10

Kovge