Selecting multiple counts with left outer join - php

I've got 3 tables: Product, Shares, Likes which are connected by ProductID. What I want to do is to select all products and COUNT(shares) and COUNT(likes) of these products in one query.
First of all is it possible to do with just one query? If possible how can i do it? And most importantly should I select all products and display then when users hover on make an Ajax call and get like and share data? Thanks in advance.

Here you go:
SELECT
p.id AS 'product id',
IFNULL(COUNT(DISTINCT s.id), 0) AS 'total shares',
IFNULL(COUNT(DISTINCT l.id), 0) AS 'total likes'
FROM
products p
LEFT JOIN shares s ON s.product_id = p.id
LEFT JOIN likes l ON l.product_id = p.id
GROUP BY p.id
IFNULL will treat cases when there are no shares or likes; DISTINCT should be there because otherwise one share will be counted multiple times when joined with likes (and vice versa).

Its possible to do it on one query. Off the top of my head something like
SELECT
product_id,
COUNT(likes.product_id) as likes,
COUNT(SELECT share_id FROM shares WHERE product_id = p.product_id) as shares
FROM product p
LEFT JOIN likes USING(product_id)
Do watch performance though. Make sure you have your indexes etc

SELECT
p.ProductID,
COUNT(s.ProductID) AS SharesCount,
COUNT(l.ProductID) AS LikesCount
FROM
Products p LEFT JOIN Shares s
ON P.ProductID = s.ProductID
LEFT JOIN likes l
ON P.ProductID = l.ProductID
GROUP BY p.ProductID

Related

Limit values for the left Join part of a query

Please i have four tables joined together using the LEFT JOIN, the images table is linked to the items table by img_item, thus each item can have more images. i want to fetch only the first image of every item. How do i go achieve this.
SELECT * FROM items
LEFT JOIN category ON items.item_cat = category.cat_id
LEFT JOIN users ON users.user_id=items.item_user
LEFT JOIN institutions ON institutions.inst_id=users.user_inst
LEFT JOIN images ON images.img_item = items.item_id
ORDER BY item_id DESC
In MySQL, you can enumerate the results using variables, and then choose the first. Another alternative is to identify which one you want, and choose that one. The following chooses the image with the largest id:
SELECT *
FROM items LEFT JOIN
category
ON items.item_cat = category.cat_id LEFT JOIN
users
ON users.user_id=items.item_user LEFT JOIN
institutions
ON institutions.inst_id = users.user_inst LEFT JOIN
images
ON images.img_item = items.item_id AND
images.img_id = (SELECT MAX(i2.img_id)
FROM images i2
WHERE i2.img_item = images.img_item
);
ORDER BY item_id DESC

Show null results when left join don't find match

I have problem with join left. It work fine but i don't see null results. It connects three tables - categories, product_categories and order_products.
Query made by stack user look's like:
SELECT
categories.name,categories.id,
SUM((orders_products.product_price_gross + orders_products.option_price)*(1 - (orders_products.rebate/100)) * orders_products.product_qty) as suma
FROM orders_products
LEFT JOIN product_categories
ON product_categories.product_id = orders_products.product_id
LEFT JOIN categories
ON product_categories.category_id = categories.id
GROUP BY categories.name, categories.id
ORDER BY suma DESC
I'm not sure how upgrade this query - I need to see what never been sold to show on shop statistics.
I hope You could help me.
Kind regards
Mark
You want to see products that has not been sold? Your main table is the transaction table orders_products. So any product not "ordered" will not show. Interchange product_categories and orders_products to achieve what you want. This will list all categories and null out the "suma" if JOIN statement cannot find the product_id listed in the "order_products" table
SELECT
categories.name,
categories.id,
SUM((orders_products.product_price_gross + orders_products.option_price)*(1 - (orders_products.rebate/100)) * orders_products.product_qty) AS suma
FROM product_categories
LEFT JOIN orders_products
ON product_categories.product_id = orders_products.product_id
LEFT JOIN categories
ON product_categories.category_id = categories.id
GROUP BY categories.name, categories.id
ORDER BY suma DESC

products with multiple option filters mysql and php

I am setting up a database with the following layout:
prodCategory (ID,name)
prodsToCategory (cat_id, prod_id)
Products (ID, name, desc etc)
prodsToOptions (prod_id, cat_id)
prodOptions (ID, type, name)
I am looking for the most efficient mysql query to join the tables and return only the products with what options have been selected.
I currently have:
SELECT
p.ID,
p.name,
p.description,
p.code,
po.name
FROM
Products p
LEFT OUTER JOIN prodsToCategory pc ON p.ID = pc.product_id
LEFT OUTER JOIN prodsToOptions pto ON p.ID = pto.product_id
LEFT OUTER JOIN prodOptions po ON pto.option_id = po.ID
WHERE p.active = '1'
AND pc.category_id = '1'
AND (po.name = 'black' OR po.name = 'blue')
GROUP BY p.ID
The url would look something like this:
www.test.com/cars?options=black-blue-manual etc (posted with ajax)
The above query does work but i'm sure there is a cleaner way of doing it when more options are set.
Any suggestions are gratefully received, even if the DB schema need changing.
Thanks in advance
Use, AND po.name IN('black','blue')

MySQL - WHERE / HAVING count

I searched lots of similar topics about this but can't find the answer to this specific probem.
So I have a table with categories and I have another table with products, so what I want is select all the categories that contain at least 1 product, seems very easy but the following code dont give me what I expect.
SELECT *
FROM categories
INNER JOIN products on (categories.id = products.cat_id)
HAVING count(products.cat_id) > 0
All help is appreciated.
Thank you!
You can actually get what you want with just a join because any categories without products will not match.
You should also add a DISTINCT or GROUP BY to remove the duplicate category records from the results:
SELECT DISTINCT c.*
FROM categories c
JOIN products p
ON c.id = p.cat_id
OR:
SELECT c.*
FROM categories c
JOIN products p
ON c.id = p.cat_id
GROUP BY c.id
If you want something fancy like categories that have 2 or more products then you can use GROUP BY and HAVING:
SELECT c.*
FROM categories c
JOIN products p
ON c.id = p.cat_id
GROUP BY c.id
HAVING count(*) >= 2
Try this select in this select all categories that have at least one product
select categories.* from categories
left join products on (categories.id = products.cat_id)
where products.cat_id IS NOT NULL
group by categories.id
In this case you're not using "HAVING" but will have the same result

How to query 3 tables in a single query?

I'm really sorry for the first post as i didn't explain everything.
Basically i have 3 tables, One for posts, One for Categories, & Another to link categories with posts.
I want in a single MySQL query to select posts that are under a specific category.
posts(id,title,body)
---------------------
125,Some title,Blah blah
categories(id,name)
---------------------
1,politic
2,entertainment
linker(categoryid,postid)
---------------------
2,125
I want in single query to fetch posts in the entertainment category by example, what to do?
Thanks
select
p.*
from
posts p
inner join linker l on l.postid = p.id
inner join categories c on c.categoryid = l.categoryid
where
c.name = 'entertainment'
The following SQL statement should provide you with a basis for what you are trying to do.
select p.*
from posts p
inner join linker l
on l.postid = p.id
inner join categories c
on l.categoryid = c.id
where c.name = 'entertainment'
If a post belongs to 2 categories, you can still use pinkfloydx33's query with DISTINCT in the select statement:
select
DISTINCT p.*
from
posts p
inner join linker l on l.postid = p.id
inner join categories c on c.categoryid = l.categoryid
where
c.name = 'entertainment'
The result set will show only one record.
It's the same exact thing, you just have to join 3 tables intead of 2 :
SELECT P.id post_id,
P.title,
P.body,
C.id category_id,
C.name
FROM posts P
INNER JOIN linker L
ON P.id = L.postid
INNER JOIN categories C
ON L.categoryid = C.id
WHERE C.name = 'Category'
Don't be afraid to do your own tests. If you understand how to join two tables, you should understand how to join three, four and more.
If you are specifying only one category in the WHERE clause, then the result will be a single row for each post ID.
Either way you can use DISTINCT or GROUP BY when the result could be more than one row per ID, but in that case i prefer the second one (GROUP BY).

Categories