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;
Related
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
I have two tables called work and stuff both tables have same fields -
company, quality, quantity
I need the sum of all the quantity of work with group by company and quality and join the table with sum of all the quantity of stuff with group by company and quality
I didn't get the expected result.
SQLfiddel
http://sqlfiddle.com/#!9/eea577/6
working query
select st.company,st.quality,st.quantitys - ct.quantitys as balance from
(select company,quality,sum(quantity) as quantitys from stuff
group by quality,company) as st join (select company,quality,
sum(quantity) as quantitys from work group by quality,company)
as ct on `ct`.`company` = `st`.`company` and ct.quality = st.quality group by quality,company
u have missed the quality condition in the join
Try the following:
SELECT tableA.ID, tableA.`Year`, tableA.`Month`,
tableA.`Type`, tableA.instrument,
tableA.totalAmount, tableB.totalInstrument
FROM
(
SELECT a.ID, a.`Year`, a.`Month`,
b.`Type`, b.instrument,
SUM(b.`amount`) totalAmount
FROM `date` a
INNER JOIN `transactions` b
ON a.ID = b.id
GROUP BY b.`Type
) tableA
INNER JOIN
(
SELECT a.ID, a.`Year`, a.`Month`,
b.`Type`, b.instrument,
SUM(b.`instrument`) totalInstrument
FROM `date` a
INNER JOIN `transactions` b
ON a.ID = b.id
GROUP BY a.`Year`, a.`Month`
) tableB ON tableA.ID = tableB.ID AND
tableA.`Year` = tableB.`Year` AND
tableA.`Month` = tableB.`Month`
I have a pretty big query which is used by an ajax call to return and also sort active items. From my understanding sub queries should be avoided where possible and since this query will be called very often, I would like to do just that.
At the moment everything is fine except for the COUNT(b.bic) AS bids. If there are two(2) bids the query returns four(4), if there are 4, it returns 8, and so on. I've tried grouping by other columns ... but no luck.
Some of the tables. I hope each of the column names are pretty self explanatory:
countries_ship - each item can be shipped to multiple countries so item_id can be duplicate.
id item_id country_id ship_cost
countries
id country_code country_name
item_expire - not sure if item_expire should have it's own table.
id item_id exp_date
bids - Just as countries_ship, item_id can be duplicate. This is where the bids are stored.
id item_id user_id bid previous_bid bid_date
The query:
$q = $this->db->mysqli->prepare("
SELECT c.ship_cost,
c.item_id,
co.country_name,
co.id AS co_id,
i.id,
i.user_id,
i.item_start,
i.item_title,
i.item_number,
i.item_year,
i.item_publisher,
i.item_condition,
i.item_description,
i.item_location,
e.exp_date AS exp_date,
i.active,
CAST(u.fb_id AS CHAR(50)) AS fb_id,
u.user_pic,
MAX(b.bid) AS maxbid,
COUNT(b.bid) AS bids,
p.publisher_name,
t.tag_name
FROM countries_ship c
JOIN items i
ON c.item_id = i.id
JOIN item_expire e
ON c.item_id = e.item_id
JOIN users u
ON i.user_id = u.id
LEFT JOIN bids b
ON i.id = b.item_id
LEFT JOIN publishers p
ON i.item_publisher = p.id
LEFT JOIN tags_rel tr
ON c.item_id = tr.item_id
JOIN tags t
ON t.id = tr.tag_id
LEFT JOIN countries co
ON i.item_location = co.id
WHERE ".$where."
GROUP BY c.item_id ORDER BY ".$order." ".$limit."");
You may try
COUNT(distinct b.bic) AS bids
This will ignore duplicates due to joins
I wish to join multiple tables like- Categories, menus, restaurants, reviews, etc.
to return the restaurants that provide the inserted food with their prices.
Everything works except numberOfReviews in reviews table.
If a restaurant has no reviews then output should be 0 for numOfReviews column but other column values should be retrieved i.e. price, name, etc.
With following query I get all fields as null and count(numReviews) as 0:
select r.id
,r.`Name`
,r.`Address`
,r.city
,r.`Rating`
,r.`Latitude`
,a.`AreaName`
,m.`Price`
,count(rv.id)
from `categories` c, `menus` m, `restaurants` r, areas a, reviews rv
where m.`ItemName`="tiramisu"
and c.`restaurant_id`=r.`id`
and m.`category_id`=c.id
and r.`AreaId`=a.`AreaId`
and if I can't match rv.restaurant_id=r.id in where clause(obviously).
Where am I getting wrong? How do I solve this?
edited
select r.id,
r.`Name`,
r.`Address`,
r.city,
r.`Rating`,
r.`Latitude`,
a.`AreaName`,
m.`Price`,
r.`Longitude`,
r.Veg_NonVeg,
count(rv.id)
from restaurants r LEFT JOIN `reviews` rv on rv.`restaurant_id`=r.`id`
inner join `categories` c on c.`restaurant_id` = r.id
inner join `menus` m on m.`category_id` = c.id
inner join `areas` a on a.`AreaId` = r.`AreaId`
where m.`ItemName`="tiramisu"
First of all, don't use this old school syntax for the jointures.
Here is a query that may solve your problem:
SELECT R.id
,R.Name
,R.Address
,R.city
,R.Rating
,R.Latitude
,R.Longitude
,A.AreaName
,M.Price
,R.Veg_NonVeg
,COUNT(RV.id) AS numOfReviews
FROM restaurants R
INNER JOIN categories C ON C.restaurant_id = R.id
INNER JOIN menus M ON M.category_id = C.id
INNER JOIN areas A ON A.AreaId = R.AreaId
LEFT JOIN reviews RV ON RV.restaurant_id = R.id
WHERE M.ItemName = 'tiramisu'
GROUP BY R.id, R.Name, R.Address, R.city, R.Rating, R.Latitude, R.Longitude, A.AreaName, M.Price, R.Veg_NonVeg
I used explicit INNER JOIN syntax instead of your old school syntax and I modified the jointure with table reviews in order to get the expected result. The GROUP BY clause is required to use the aggregate function COUNT, every rows will be grouped by the enumerated columns (every column except the one used by the function).
Here is another solution that simplify the GROUP BY clause and allow the modification of SELECT statement without having to worry about the fact that every columns need to be part of the GROUP BY clause:
SELECT R.id
,R.Name
,R.Address
,R.city
,R.Rating
,R.Latitude
,R.Longitude
,A.AreaName
,M.Price
,R.Veg_NonVeg
,NR.numOfReviews
FROM restaurants R
INNER JOIN (SELECT R2.id
,COUNT(RV.id) AS numOfReviews
FROM restaurants R2
LEFT OUTER JOIN reviews RV ON RV.restaurant_id = R2.id
GROUP BY R2.id) NR ON NR.id = R.id
INNER JOIN categories C ON C.restaurant_id = R.id
INNER JOIN menus M ON M.category_id = C.id
INNER JOIN areas A ON A.AreaId = R.AreaId
WHERE M.ItemName = 'tiramisu'
As you can see here I added a new jointure on a simple subquery that does the aggregation job in order to provide me the expected number of reviews for each restaurant.
Hope this will help you.
I have 3 tables:
shops, PRIMARY KEY cid,zbid
shop_items, PRIMARY KEY id
shop_inventory, PRIMARY KEY id
shops a is related to shop_items b by the following: a.cid=b.cid AND a.zbid=b.szbid
shops is not directly related to shop_inventory
shop_items b is related to shop_inventory c by the following: b.cid=c.cid AND b.id=c.iid
Now, I would like to run a query which returns a.* (all columns from shops). That would be:
SELECT a.* FROM shops a WHERE a.cid=1 AND a.zbid!=0
Note that the WHERE clause is necessary.
Next, I want to return the number of items in each shop:
SELECT
a.*,
COUNT(b.id) items
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid
As you can see, I have added a GROUP BY clause for this to work.
Next, I want to return the average price of each item in the shop. This isn't too hard:
SELECT
a.*,
COUNT(b.id) items,
AVG(COALESCE(b.price,0)) average_price
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid
My next criteria is where it gets complicated. I also want to return the unique buyers for each shop. This can be done by querying shop_inventory c, getting the COUNT(DISTINCT c.zbid). Now remember how these tables are related; this should only be done for the rows in c which relate to an item in b which is owned by the respective shop, a.
I tried doing the following:
SELECT
a.*,
COUNT(b.id) items,
AVG(COALESCE(b.price,0)) average_price,
COUNT(DISTINCT c.zbid)
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
LEFT JOIN shop_inventory c ON c.cid=b.cid AND c.iid=b.id
WHERE a.cid=1
GROUP BY b.szbid,b.cid
However, this did not work as it messed up the items value. What is the proper way to achieve this result?
I also want to be able to return the total number of purchases made in each shop. This would be done by looking at shop_inventory c and adding up the c.quantity value for each shop. How would I add that in as well?
Try this solution:
SELECT a.*,
COALESCE(b.item_cnt, 0) AS item_cnt,
COALESCE(b.avg_price, 0) AS avg_price,
COALESCE(b.buyer_cnt, 0) AS buyer_cnt
FROM shops a
LEFT JOIN (
SELECT a.cid,
a.szbid,
COUNT(*) AS item_cnt,
AVG(a.price) AS avg_price,
b.buyer_cnt
FROM shop_items a
LEFT JOIN (
SELECT cid,
iid,
COUNT(DISTINCT zbid) AS buyer_cnt
FROM shop_inventory
WHERE cid = 1
GROUP BY cid,
iid
) b ON a.cid = b.cid AND a.id = b.iid
WHERE a.cid = 1 AND
a.szbid <> 0
GROUP BY a.cid,
a.szbid
) b ON a.cid = b.cid AND a.zbid = b.szbid
WHERE a.cid = 1 AND
a.zbid <> 0
Instead of COUNT(DISTINCT c.zbid) + LEFT JOIN shop_inventory you could write a subselect:
SELECT
a.*,
COUNT(b.id) items,
AVG(COALESCE(b.price,0)) average_price,
( SELECT COUNT(DISTINCT c.zbid)
FROM shop_inventory c
WHERE c.cid=b.cid AND c.iid=b.id
)
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid