MySQL join with specific WHERE clause - php

I have a simple database
With this query I get all users and number of products they have bought:
SELECT
c.id,
cd.name,
cd.surname,
COUNT(p.name) as bought
FROM shopping s
JOIN client c ON s.client_id = c.id
JOIN client_details cd ON c.id = cd.client_id
JOIN product p ON s.product_id = p.id
GROUP BY c.id;
It's pretty good, but I have to select all users and number of specific products bought. With this query I get it only if the user have bought at least one product:
SELECT
c.id,
cd.name,
cd.surname,
COUNT(p.name) as bought
FROM shopping s
JOIN client c ON s.client_id = c.id
JOIN client_details cd ON c.id = cd.client_id
JOIN product p ON s.product_id = p.id
WHERE p.name = 'sugar'
GROUP BY c.id;
I want to get the list with all users, and if specific user didn' buy specific product, there should be 0 on output.

Use condition aggregation:
SELECT c.id, cd.name, cd.surname,
MAX(p.name = 'sugar') as SugarFlag
FROM shopping s JOIN
client c
ON s.client_id = c.id JOIN
client_details cd
ON c.id = cd.client_id JOIN
product p
ON s.product_id = p.id
GROUP BY c.id;

Related

Improve this query with use of union

This query gives an error if subquery return more than 1 row. I separated the queries and use mysqli_multi_query(), but both queries data is displayed in two tables.
So I decided to make the one query.
SELECT DISTINCT category ,
(SELECT COUNT(products.name)
FROM products
where category_id=categories.id
) AS total_products,
(
SELECT SUM(quantity) FROM productstock a
LEFT JOIN products b ON a.product_id=b.id
LEFT JOIN categories c ON b.category_id=c.id
where c.deleted=0
GROUP BY category_id
) AS available_stock,
SUM(product_qty*orignalCost) AS SaleWise_cost,
SUM(product_qty*saleprice) AS SaleWise_price,
SUM(product_qty*saleprice) AS total_sale ,
SUM((product_qty*saleprice)-(product_qty*orignalCost)) AS profit
FROM categories
INNER JOIN products ON categories.id = products.category_id
INNER JOIN sales ON sales.product_id = products.id
INNER JOIN productstock ON productstock.product_id = products.id
WHERE categories.deleted=0
GROUP BY category_id
As available stock is corelated subquery so joining condition must be added in where clause inside subquery. please check this pseudocode
(
SELECT SUM(quantity) FROM productstock a
LEFT JOIN products b ON a.product_id=b.id
LEFT JOIN categories c ON b.category_id=c.id
where c.deleted=0 AND b.category_id = categories.id
) AS available_stock
Another way
(SELECT SUM(quantity)
FROM products b
INNER JOIN productstock a
ON b.id = a.product_id
AND b.id = products.id
AND b.category_id = categories.id) AS available_stock

Slow mysql query using Doctrine

To filter the products that belongs to the selected filters, I wrote this query below. When i run this in Mysql, it is very fast. But when i'm trying to execute this query in Doctrine, it is very slow. Removing the group by gives me one result and than it is fast, but it has to be 11 results.
Even the more filters i add to this statement, the slower it gets.
Can anyone help me out with this problem?
SELECT DISTINCT p.id, p.brand_id, p.name, p.permalink, p.base_model,
p.ean, p.description, p.unit, p.price, p.offer_active, p.offer_price,
GROUP_CONCAT(DISTINCT m.url ORDER BY `m`.`order`, `p`.`id` SEPARATOR ",") AS url, pcm.category_id
FROM product p
LEFT JOIN product_category pc ON pc.product_id = p.id
LEFT JOIN media m ON p.id = m.product_id
INNER JOIN product_category pcm ON p.id = pcm.product_id AND pcm.main = 1 AND pcm.product_id IS NOT NULL
LEFT JOIN product_filter_value pfv1 ON p.id = pfv1.product_id
LEFT JOIN product_filter_value pfv2 ON p.id = pfv2.product_id
LEFT JOIN product_filter_value pfv3 ON p.id = pfv3.product_id
LEFT JOIN product_filter_value pfv4 ON p.id = pfv4.product_id
WHERE (pc.category_id = 23)
AND (p.active = 1)
AND (pfv1.filter_value_id IN (2))
AND (pfv2.filter_value_id IN (8))
AND (pfv3.filter_value_id IN (22))
AND (pfv4.filter_value_id IN (38))
GROUP BY 1
ORDER BY p.top desc

MySQL query search using joins

I have the following tables:
products table
-------------
id
name
...
categories table
----------------
id
name
product_categories table
------------------------
product_id
category_id
product_ratings
---------------
product_id
user_id
rating (1 to 5 INT)
How can I select (search) products and rating (average) by Category (name or id) and order them by Title or by rating.
I have tried some queries but im having some trouble on how to join tables and how to use where clause
Do you mean something like that?
select
products.name, categories.name, product_ratings.rating
from products
join product_categories on products.id = product_categories.product_id
join categories on categories.id = product_categories.category_id
join product_ratings on product_ratings.product_id = products.id
where
categories.name = 'CATEGORY NAME'
order by
product_ratings.rating
select p.name, r.rating
from products as p
inner join product_ratings as r on p.id = r.product_id
inner join categories as c on c.id = pc.category_id
inner join product_categories as pc = pc.product_id = p.id
where c.name = 'search_name'
order by r.rating;
Method 1
Rating by product and user id
SELECT
P.name, PR.user_id , IFNULL(PR.rating,0) as rating
FROM products P
JOIN product_categories PC ON P.id = PC.product_id
JOIN categories C ON C.id = PC.category_id
JOIN product_ratings PR ON PR.product_id = P.id
WHERE C.name = 'Category A'
ORDER BY P.name
Refer http://sqlfiddle.com/#!9/014af/6
Method 2
Rating by product id
Different users will rate the same product, so we have to consider the average rating of each product.
SELECT
P.name, GROUP_CONCAT(PR.user_id) as user_ids, AVG(IFNULL(PR.rating,0)) as rating
FROM products P
JOIN product_categories PC ON P.id = PC.product_id
JOIN categories C ON C.id = PC.category_id
JOIN product_ratings PR ON PR.product_id = P.id
WHERE C.name = 'Category A'
GROUP BY P.id
ORDER BY P.name
Refer http://sqlfiddle.com/#!9/014af/7

Combine two MySql into one query

I have two sql queries that I need to combine into one query for better efficiency, just not sure how to do it. Basically I need to query my Supplier, then for each supplier check to see if the Listing table has more than one record that matches based upon "supplier id", if it does then I need to return the supplier name and id. Here are my two queries:
Query 1:
SELECT s.name, s.id
FROM Supplier s
Query 2:
SELECT l.asin,
l.id,
COUNT(*) c
FROM Listing l
LEFT JOIN Product p
ON p.id = l.product_id
LEFT JOIN Supplier s
ON p.supplier_id = s.id
WHERE (l.matchValidated IS NULL OR l.matchValidated = 0)
AND s.id = SUPPLIER_ID_GOES_HERE
GROUP BY l.asin HAVING c > 1);
You already have supplier joined in the second query so you just need to add the supplier name and id to your SELECT and GROUP BY.
SELECT l.asin,
l.id,
s.name AS supplier_name,
s.id AS supplier_id,
COUNT(*) c
FROM Listing l
LEFT JOIN Product p
ON p.id = l.product_id
LEFT JOIN Supplier s
ON p.supplier_id = s.id
WHERE (l.matchValidated IS NULL OR l.matchValidated = 0)
GROUP BY l.asin, l.id, s.name, s.id
HAVING c > 1;

MYSQL customizable join and select

i want to use JOIN categories c ON c.id = i.category if post_type is 1 and i want to have c.title AS category_name, in SELECT otherwise JOIN categories c ON c.id = i.category and c.title AS category_name, must be not worked in query , i'm using case for join but my sql command is not correct. please help me. in all description my quastion means is how to change this below command to if post_type is 1 join must be not work
SELECT SQL_CALC_FOUND_ROWS
i. * ,
c.title AS category_name,
s.title AS status_title,
i.thumb_image,
CONCAT( u.name, ' ', u.family ) AS author
FROM contents i
LEFT JOIN categories c
ON i.category = CASE post_type WHEN 1 then c.id END
JOIN users u ON u.id = i.posted_by
JOIN status_topics s ON s.id = i.t_status
WHERE i.id = 2
I would always do the LEFT JOIN and put a condition on the column itself:
SELECT SQL_CALC_FOUND_ROWS
i. * ,
IF(i.post_type = 1, c.title, NULL) AS category_name,
s.title AS status_title,
i.thumb_image,
CONCAT( u.name, ' ', u.family ) AS author
FROM contents i
LEFT JOIN categories c ON i.category = c.id
JOIN users u ON u.id = i.posted_by
JOIN status_topics s ON s.id = i.t_status
WHERE i.id = 2

Categories