Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL to join one table to another table multiple times? (Mapping products to categories)

Tags:

sql

join

Let's say I have a Product, Category, and Product_To_Category table. A Product can be in multiple categories.

    Product                     Category        Product_to_category
    ID   |   NAME               ID  | Name      Prod_id | Cat_id
    =====================       ============    ===================
        1| Rose                    1| Flowers          1| 1
        2| Chocolate Bar           2| Food             2| 2
        3| Chocolate Flower                            3| 1
                                                       3| 2

I would like an SQL query which gives me a result such as

    ProductName      | Category_1 | Category_2 | Category_3
    =======================================================
    Rose             | Flowers    |            |
    Chocolate Flower | Flowers    | Food       |

etc.

The best way I've been able to get this is to union a bunch of queries together; one query for every expected number of categories for a given product.

select p.name, cat1.name, cat2.name
from
  product p, 
  (select * from category c, producttocategory pc where pc.category_id = c.id) cat1,
  (select * from category c, producttocategory pc where pc.category_id = c.id) cat2
where p.id = cat1.id 
  and p.id = cat2.id
  and cat1.id != cat2.id
union all
select p.name, cat1.name, null
from
  product p, 
  (select * from category c, producttocategory pc where pc.category_id = c.id) cat1
where p.id = cat1.id 
  and not exists (select 1 from producttocategory pc where pc.product_id = p.id and pc.category_id != cat1.id)

There are several problems with this.

  • First, I have to repeat this union for each expected category; if a product can be in 8 categories I'd need 8 queries.
  • Second, the categories are not uniformly put into the same columns. For example, sometimes a product might have 'Food, Flowers' and another time 'Flowers, Food'.

Does anyone know of a better way to do this? Also, does this technique have a technical name?

like image 986
Mr. Shiny and New 安宇 Avatar asked Apr 20 '09 18:04

Mr. Shiny and New 安宇


People also ask

How do I combine data from multiple tables into one table in SQL?

Multiple tables can be merged by columns in SQL using joins. Joins merge two tables based on the specified columns (generally, the primary key of one table and a foreign key of the other).

What kind of join combines records for more than 2 tables?

SQL JOIN is a clause that is used to combine multiple tables and retrieve data based on a common field in relational databases. Database professionals use normalizations for ensuring and improving data integrity. In the various normalization forms, data is distributed into multiple logical tables.

What is the most efficient way of joining 2 table in same database?

Method 1: Relational Algebra Relational algebra is the most common way of writing a query and also the most natural way to do so. The code is clean, easy to troubleshoot, and unsurprisingly, it is also the most efficient way to join two tables.

Can we apply Group by clause while joining two tables?

Using Group By with Inner Join SQL Inner Join permits us to use Group by clause along with aggregate functions to group the result set by one or more columns. Group by works conventionally with Inner Join on the final result returned after joining two or more tables.


1 Answers

I don't know what RDBMS you're using, but in MySQL you can use GROUP_CONCAT:

SELECT
  p.name,
  GROUP_CONCAT(c.name SEPARATOR ', ') AS categories
FROM
  product p
  JOIN product_to_category pc ON p.id = pc.product_id
  JOIN category c ON c.id = pc.category_id
GROUP BY
  p.name
ORDER BY
  p.name,
  c.name
like image 150
Seb Avatar answered Oct 06 '22 00:10

Seb