SQL Ordering products by category order not working when product is not linked to a category

StackOverflow https://stackoverflow.com/questions/22181389

  •  05-06-2023
  •  | 
  •  

Question

I have two tables, categories and products. I am trying to do a select statement that will get all off the products and order them using the order column from the categories table.

Categories
+--------+-------+-------+
| cat_id | name  | order |
+--------+-------+-------+
|   1    | Cat 1 |   1   |
|   2    | Cat 2 |   3   |
|   3    | Cat 2 |   2   |
+--------+-------+-------+

Products
+---------+--------+-------+--------+
| prod_id | name   | price | cat_id |
+---------+--------+-------+--------+
| 1       | Prod 1 | 1.99  |   1    |
| 2       | Prod 2 | 2.99  |   2    |
| 3       | Prod 3 | 3.99  |   3    |
| 4       | Prod 4 | 4.99  |   0    |
| 5       | Prod 5 | 4.99  |   2    |
+---------+--------+-------+--------+

I managed to build this SQL statement to accomplish that.

SELECT p.* FROM products AS p
JOIN categories AS c
ON c.cat_id = i.cat_id
ORDER BY c.order ASC

The problem is that products don't have to belong to a category, and if they aren't this query will not retrieve them. While I could just perform a second query without a join and append to the first query, a problem will defintely occur when I get around to setting up pagination for the products as I think it will become too complicated calculating what products to display. Is there anything I could do?

Was it helpful?

Solution

You need to decide how you want to order them.

SELECT p.*
FROM products p LEFT JOIN
     categories AS c
     ON c.cat_id = i.cat_id
ORDER BY c.`order` ASC;

MySQL happens to put the NULL values first in an ascending sort. You probably want them last. So do this instead

SELECT p.*
FROM products p LEFT JOIN
     categories AS c
     ON c.cat_id = i.cat_id
ORDER BY (c.`order` is not null) DESC,
         c.`order` ASC;

The expression (c.order is not null) evaluates to 0 when order is defined and to 1 when it is not.

And, order is a very bad name for a column because it is a MySQL reserved word (actually, it is reserved in all databases). You might consider something like priority instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top