SQL Join 3 Tables and concatenate values - mysql

I have 3 Tables with a n:m Relation
Languages:
ID (primary-key)
name
slug
Products:
ID
name
slug
-productgroup
Table for Relation:
Lang_Prod:
lang_prod_id (composed from lang_id and prod_id)
lang_id
prod_id
Now i want to get all Products with their corresponding Language-Names:
product
productgroup
language-names (multiple values)
I've tried:
SELECT product.*, languages_products.language_id,
GROUP_CONCAT(languages_products.language_id) as languages
FROM product
INNER JOIN languages_products ON id = languages_products.product_id
GROUP BY product.id;
Result is:
productname
product_slug
product_group
String with languages IDs
Instead of the string with the language-IDs, i would like to have a string with language-names
How can i archieve that?

You need to join with language table
SELECT product.id,product.name,product.productgroup,
GROUP_CONCAT(l.name) as languages
FROM product
INNER JOIN languages_products ON id = languages_products.product_id
INNER JOIN languages l ON languages_products.language_id=l.id
GROUP BY product.id,product.name,product.productgroup

You need to add another join with the languages table, and use the name column from it. I'd group it in an inner query though:
SELECT p.*, languages
FROM product p
JOIN (SELECT product_id, GROUP_CONCAT(l.name) as languages
FROM languages_products lp
JOIN languages l ON lp.language_id = l.id
GROUP BY product_id) cl ON cl.product_id = p.id

Related

SQL JOIN: Select Records from Another Table With Matching IDs

I am having trouble building a correct SQL JOIN statement to select some records from another table.
--Table Product:
ID
Name
CatID1
CatID2
and
--Table Category:
CatID
CategoryName
Product.CatID1, Product.CatID2 are referenced to Category.CatID
So I really want to select Product fields and replace Product.CatID1, Product.CatID2 with Category.CategoryName (for Product.CatID1) and Category.CategoryName (for Product.CatID2).
This obviously does not work but explains what I need:
SELECT Product.ID, Product.Name,
Category.CategoryName as Product.CatID1,
Category.CategoryName as Product.CatID2
from product, categories;
All you need is a double LEFT JOIN to categories table:
SELECT p.ID, p.Name,
c1.CategoryName as CatID1,
c2.CategoryName as CatID2
from product AS p
LEFT JOIN categories AS c1 ON p.CatID1 = c1.CatID
LEFT JOIN categories AS c2 ON p.CatID2 = c2.CatID
If there is no match for either CatID1 or CatID2, the corresponding field in the SELECT clause is going to be NULL.
SELECT Product.ID,
Product.Name,
C1.CategoryName as Product.CatID1,
C2.CategoryName as Product.CatID2
FROM Product JOIN Category C1 ON C1.CatID = CatID1
JOIN Category C2 ON C2.CatID = CatID2 ;
Use the category table twice.
What if you decide, in the future, that a product can be in 3 categories? Really, you should have a joining table for these and remove the repeating info from Product.

Pull data from 3 tables

I have 3 tables as follows :
Table 1: Product
id_product [Primary Key],added_time.
Table 2: Category
id_category [Primary Key],Category_name.
Table 3: product_category
id_category,id_product [Both Foreign Keys]
I want to pull Data as
Category_name,No Of Products in this Category,Last time when product was added to Category(Latest product added_time).
You could use this SQL:
SELECT Category.Category_name,
Count(DISTINCT Product.id_product) AS num_products,
Max(Product.added_time) last_added_time
FROM Category
LEFT JOIN product_category
ON product_category.id_category = Category.id_category
LEFT JOIN Product
ON Product.id_product = product_category.id_product
GROUP BY Category.Category_name;
Note that by using LEFT JOIN you will be certain to list all categories even those for which no products exist. If you don't want those, replace both LEFT keywords with INNER.
Note also that in standard SQL you need to GROUP BY any columns you mention in the SELECT list, unless they are aggregated, like with MAX or COUNT.
SELECT C.`Category_name`,
(SUM(IF(P.`id_product`IS NULL,0,1))) AS No_of_Products,
MAX(P.`added_time`) AS Latest_time
FROM
Category C
LEFT JOIN
product_category P_C ON C.`id_category` = P_C.`id_category`
LEFT JOIN
Product P ON P.`id_product` = P_C.`id_product`
GROUP BY C.`id_category`
Hope this helps.

How to get names of relevant ID's from 2 different tables and display them

I have 3 tables, First one has the product ID and Name, Second one has Supplier ID and name, In the 3rd one i have product ID and Supplier ID. While displaying, i want to replace the product ID and supplier ID in the 3rd table with product name and supplier name from the 1st and 2nd table respectively.
Please let me know the query for executing it.
Reference: http://dev.mysql.com/doc/refman/5.7/en/join.html
SELECT * FROM table1
INNER JOIN table2
ON table1.id=table2.id
INNER JOIN table3
ON table2.id=table3.id;
If your tables are named products_master, stockists_master, and stockist_product_offer, then you can join the tables and select any of the six columns that you want.
SELECT product_master.name, stockists_master.name
FROM products_master
INNER JOIN stockist_product_offer
ON product_master.id = stockist_product_offer.product_id
INNER JOIN stockists_master
ON stockist_product_offer.stockist_id = stockist.id;
you have to join the tables on IDs so the query is :
let s say that :
* first table : product
* second table : supplier
* third table : match
SELECT P.PRODUCTNAME
S.SUPPLIERNAME
FROM
PRODUCT P
INNER JOIN
MATCH M
ON P.PRODUCTID = M.PRODUCTID
INNER JOIN
SUPPLIER S
ON S.SUPPLIERID = M.SUPPLIERID
ORDER BY 1
;

select all books from one category except books which belong to other category

I have 3 tables: books, book_categories, categories.
book_categories table "joins" books and categories. It contains columns: id,book_id,category_id.
So one Book may belong to many categories and one Categorie may have many books.
I need query which retrieves all books from given_category except books which belongs to given_set_of_categories. So for example I want all books from category A but only if they don't belong also to category B or C. I need also sort (order) the result by Book.inserted column.
I know how to get all books from given_category with 2 joins but can't figure out how to exclude some books from other categories in result. I cant filter books in PHP because I am paginating the search result.
where
category_id = <given category>
and books.book_id not in
(
select book_id from book_categories
where category_id in (<given set of cat>)
)
order by books.inserted
So, if you mean it is in one category but not in any other:
AND EXISTS(SELECT * FROM books b JOIN book_categories bc ON b.id = bc.book_id JOIN categories c ON bc.category_id = c.id AND c.id = 'A')
AND NOT EXISTS(SELECT * FROM books b JOIN book_categories bc ON b.id = bc.book_id JOIN categories c ON bc.category_id = c.id AND c.id != 'A')
I think that this can be achieved through counting provided that book_categories entries are unique, thus the combination book_id & category_id are not repeating. Instead of trying directly to exclude records, we select from the combined set of categories [,] and then we'll count book_id entries that belong to the :
COUNT(IF(category_id = <given_category>, 1, NULL)) as cnt_exists
and after ensuring that it contains the required category, we count the total to see if it belongs to any other category as well:
COUNT(*) AS cnt_total
SELECT * FROM books b JOIN (
SELECT book_id,
COUNT(IF(category_id = <given_category>, 1, NULL)) as cnt_exists,
COUNT(*) AS cnt_total FROM book_categories WHERE
category_id IN(<given_category>, <given_set_of_categories>)
) bc ON b.id = bc.book_id AND
cnt_exists = 1 AND cnt_total = 1 ORDER BY b.inserted

selecting from multiple tables with counter

I have two tables one holds a category with column catID,catName and the other has the catID as a foreign key, now i want to select all the total items on the second table based on their catID.
E.g. What is the total number of individual element if their category is 1,2,3,4 etc. Pls code hints will help thanks.
SELECT
c.cat_id
,count(*) as occurence
FROM category c
INNER JOIN table2 t ON (c.cat_id = t.cat_id)
GROUP BY c.cat_id
If you want the categories with occurence = 0 then do:
SELECT
c.cat_id
,count(t.cat_id) as occurence
FROM category c
LEFT JOIN table2 t ON (c.cat_id = t.cat_id)
GROUP BY c.cat_id
Links:
http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html
http://www.1keydata.com/sql/sqlgroupby.html
SELECT catName, COUNT(table2.catId) FROM table1,table2
WHERE table1.catId=table2.catId
GROUP BY catName