• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 299
  • Last Modified:

Order by column with multiple values

I have a products table in my db which has a category field which relates to another table.

For example:

prodId   prodName   prodCat
1            test              2
2            test 2           2
3            test 3           1
4            test 4           1
5            test 5           2

The category table has id, name and order:

catID   catName   catOrder
1         cat1           3,4
2         cat2           1,2,5

The catOrder field is just a collection of the product ID's, what I want is to display the products table but in the order which appears in the catOrder column.

I currently have the following in my SQL:

SELECT store.*, cat.* FROM (store LEFT JOIN cat ON store.prodCat = cat.catID) WHERE store.prodCat = '" . $_GET['cat'] . "'

How would I go about splitting the catOrder field so that I can order by this field?


1 Solution
Gurvinder Pal SinghCommented:
Or you can update your table structure in this way

prodId   prodName   prodCat   order
1            test              2              1  
2            test 2           2              2
3            test 3           1              1
4            test 4           1              2
5            test 5           2              3

which will make your sql query quite simple, isn't it?
djfenomAuthor Commented:
Unfortunately the tables are already in place and there are multiple categories which need an order for each one, the only way this would work is if there was a column for each category but this isn't feasible as there is an indefinite number.
Gurvinder Pal SinghCommented:
Not sure, if there is a way to do it through a query. You will have to get the column value, split the same, and then fetch the products details for an id after iterating through all the id.
Easily Design & Build Your Next Website

Squarespace’s all-in-one platform gives you everything you need to express yourself creatively online, whether it is with a domain, website, or online store. Get started with your free trial today, and when ready, take 10% off your first purchase with offer code 'EXPERTS'.

You need to rearchitecture the database.  The way to properly handle multiple related values is to put it to a seperate table.  Something like a category_orders table the has catID and catOrder as columns, and you have one row each for every CatID-catOrder combination.  Then you can just join this table to your query.
Ray PaseurCommented:
Unfortunately the tables are already in place
Not really a problem.  You can change data base tables easily with ALTER TABLE.  In this case you should change the tables.  Going forward, you will never again want to have more than one data element in each cell.
I am not saying this is efficient, just that it should work for what you want. A lot of times reworking a database after an entire system is in place is just not useful or possible especially if it was a purchased system and changing it will affect other purchased software that runs off of it.

If this is a case of a system currently being developed or one that you or your company has permission to modify then you should try to normalize your database to at least 3rd normal form so you don't run into these problems in the future.

To handle your current situation if my hands were completely tied against changing the database, I would do something like the following

 I am going to make a few assumptions in this

1. you are using mysql_query to access your database
2. you don't want to be hacked via url parameters

also, this is off the top of my head and not tested.

$catId = mysql_real_escape_string($_GET['cat']);
$strSQL = "SELECT store.*, cat.* FROM (store LEFT JOIN cat ON store.prodCat = cat.catID) WHERE store.prodCat = '$catId'";

$result = mysql_query($strSQL);

        $row = mysql_fetch_array($result);
        $ordervals = $row['catOrder'];
        $order = explode(",",$ordervals);

//you now have an array that denotes the order to display your fields.
$index = 0;
while($row = mysql_fetch_array($result))
     if($index < mysql_num_rows($result))
         if($row['prodId'] == $order[$index])
               //add code here to display your data
               mysql_data_seek($result,0);  //set mysql result pointer back to beginning

Open in new window

Guy Hengel [angelIII / a3]Billing EngineerCommented:
this should do (untested ...)
SELECT s.*, c.* , p.*
FROM store s
  ON s.prodCat = c.catID
LEFT JOIN Product p
  ON p.prodcat = c.catid
WHERE s.prodCat = '" . $_GET['cat'] . "'
ORDER BY INSTR( CONCAT(',', c.catOrder,',') , CONCAT(',', p.ProdID, ',') ) 

Open in new window


but I agree that the design is bad ...
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now