This question already has answers here:
Query using group_concat is returning only one row
(4 answers)
Closed 2 years ago.
I am newbie in mysql, for learning i am using sample database of w3schools. in that i want to create a view which will for each supplier, list the supplier name, the count of distinct products by the supplier (PCount), the count of distinct product categories by the supplier (CCount).
here is my table structures
Suppliers Products
-------------------- ----------------------------
SupplierID ProductID
SupplierName ProductName
ContactNumber SupplierID
Address CategoryID
City Unit
PostalCode Price
Country
Phone
What i have try is
SELECT s.SupplierName, COUNT(DISTINCT(p.ProductID)) as PCount, COUNT(DISTINCT(p.CategoryID)) as CCount FROM Suppliers as s
right join Products as p
on s.SupplierID = p.SupplierID
this is only giving me single SupplierName not all the supplier details with distinct product and distinct category.
Any help would be much appreciated.
Give this a shot:
SELECT s.SupplierName,
COUNT(p1.ProductID) AS PCount,
COUNT(DISTINCT p2.CategoryID) AS CCount
FROM Suppliers s
LEFT JOIN Products p1 ON s.SupplierID=p1.SupplierID
LEFT JOIN Products p2 ON s.SupplierID=p2.SupplierID
GROUP BY s.SupplierName
ORDER BY s.SupplierName
I am not sure how else to ask the question, so I will give an example, to see if this is possible with SQL.
Let's say a customer visits a store, and a System creates a VisitID. Then he places an Order in a table of Orders, linked to the VisitID. Then he fills in a Shipping Form, in a table of ShippingForms, linked to the Visit ID. Then the system generates a Receipt, in a table of ReceiptForms, linked to the VisitID. Then he fills in a Return Form, in a table of ReturnForms, linked to the VisitID.
So, is there a way to query the system to show for a VisitID there is/isn't an Orders record, Shipping Form record, Receipt record, Return record? This would be handy in a DBGrid to show all the activities of the customer on that VisitID. Each table (Orders, ShippingForm, ReceiptForm, ReturnForm, etc.) is of a different structure and different fields, but linked by the Visit ID, and may be present or not present, or may have several Orders during that VisitID.
So -- Select Orders, ShippingForm, ReceiptForm, ReturnForm where VisitID=x.
so I could present the information in a grid such as:
{
VisitID 2315
OrderID 1256
OrderID 1257
OrderID 1258
ReceiptID 5124
ReceiptID 5125
ReceiptID 5126
ShippingID 99023
ReturnID 582812
}
Visits that do not have records in all tables:
Select *
from Visits v -- visit always exists
left join Orders o on o.visitId = v.visitId
left join ShippingForm s on s.visitId = v.visitId
left join ReceiptForm r on r.visitId = v.visitId
left join ReturnForm rf on fr.visitId - v.visitId
where v.VisitID=x
and (o.visitId is null or s.visitId is null or r.visitId is null or fr.visitId is null ) -- it is null when record does not exist
Maybe you are looking for UNION ALL:
select visitid, type, id
from
(
select visitid, 'visit' as type, 1 as sortkey, null as id from visits
union all
select visitid, 'order' as type, 2 as sortkey, orderid as id from orders
union all
select visitid, 'receipt' as type, 3 as sortkey, receiptid as id from receipts
union all
select visitid, 'shipping' as type, 4 as sortkey, shippingid as id from shippings
union all
select visitid, 'return' as type, 5 as sortkey, returnid as id from returns
) data
order by visitid, sortkey;
Or you may want string aggregation. This is DBMS dependent and you haven't mentioned your DBMS. This is for MySQL:
select
visitid,
ord.ids as orderids,
rcp.ids as receiptids,
shp.ids as shippingids,
ret.ids as returnids
from visits v
left join
(select visitid, group_concat(orderid) as ids from orders group by visitid) ord
using (visitid)
left join
(select visitid, group_concat(receiptid) as ids from receipts group by visitid) rcp
using (visitid)
left join
(select visitid, group_concat(shippingid) as ids from shippings group by visitid) shp
using (visitid)
left join
(select visitid, group_concat(returnid) as ids from returns group by visitid) ret
using (visitid)
order by visitid;
Thank you all, you have allowed me to answer the question. For my purposes, I combined the results to make this sol
select
OrderID as FormID,
1 as FormType,
'Order ID' as FormTitle
from Orders O, Visits V where (O.VisitID=V.VisitID) and (V.VisitID=112)
union all
ShippingID as FormID,
2 as FormType,
'Shipping ID' as FormTitle
from Shipping S, Visits V where (S.VisitID=V.VisitID) and (V.VisitID=112)
etc.
so now have a line by line table for VisitID=112:
FormID FormType FormTitle
23 1 Order ID
26 1 Order ID
28 1 Order ID
342 2 Shipping ID
343 2 Shipping ID
367 2 Shipping ID
I have two tables - one shows user purchases, and one shows a product id with it's corresponding product type.
My client wants to make duplicate users inactive based on last name and email address, but wants to run the query by product type (based on what type of product they purchased), and only wants to include user_ids who haven't purchased paint (product ids 5 and 6). So the query will be run multiple times - once for all people who have purchased lawnmowers, and then for all people who have purchased leafblowers etc (and there will be some overlap between these two). No user_id that has purchased paint should be made inactive.
In terms of who should stay active among the duplicates, the one to stay active will be the one with the highest product id purchased (as products are released annually). If they have multiple records with the same product id, the record to stay active will be the one with most recent d_modified and t_modified.
I also want to shift the current value of 'inactive' to the 'previously_inactive' column, so that this can be easily reversed if need be.
Here is some sample table data
If the query was run by leafblower purchases, rows 5, 6, and 7 would be made inactive. This is the expected output:
If the query was run by lawnmower purchases, rows 1 and 2 would be made inactive. This would be the expected output:
If row 4 was not the most recent, it would still not be made inactive, as user_id 888 had bought paint (and we want to exclude these user_ids from being made inactive).
This is an un-optimised version of the query for 'leafblower' purchases (it is working, but will probably be too slow in the interface):
UPDATE test.user_purchases
SET inactive = 1
WHERE id IN (
SELECT z.id
FROM (SELECT * FROM test.user_purchases) z
WHERE z.product_id IN (
SELECT product_id
FROM test.products
WHERE product_type IN ("leafblower")
)
AND id NOT IN (
SELECT a.id
FROM (SELECT * FROM test.user_purchases) a
INNER JOIN (
SELECT r.surname, r.email
FROM (SELECT * FROM test.user_purchases) r
JOIN test.products s on r.product_id = s.product_id
WHERE s.product_type IN ("paint")
) b
WHERE a.surname = b.surname
AND a.email = b.email
)
AND id NOT IN (
SELECT MAX(z.id)
FROM (SELECT * FROM test.user_purchases) z
WHERE z.product_id IN (
SELECT product_id
FROM test.products
WHERE product_type IN ("leafblower")
)
AND id NOT IN (
SELECT a.id
FROM (SELECT * FROM test.user_purchases) a
INNER JOIN (
SELECT r.surname, r.email
FROM (SELECT * FROM test.user_purchases) r
JOIN test.products s on r.product_id = s.product_id
WHERE s.product_type IN ("paint")
) b
WHERE a.surname = b.surname
AND a.email = b.email
)
GROUP BY surname, email
)
)
Any suggestions on how I can streamline this query and optimise the speed of it would be much appreciated.
I have the following three tables: Product, User and Purchased.
Product contains:
A unique identifier (productID)
A name (productname)
A price
(productprice)
User contains:
A unique identifier (userID)
Purchased contains:
Two identifiers noted as private keys, productID and userID
A date of the record (creationdate)
My query should return a list of unique products that were bought on the retailer’s site since January 1st with most expensive product returned first.
My Query:
SELECT Product.productID, Product.productname, Purchased.creationdate
FROM Product
INNER JOIN Purchased
ON Product.productID = Purchased.productID;
ORDER BY Product.productprice DESC;
If you just want a list of products, I would suggest exists rather than join:
select p.*
from products p
where exists (select 1
from purchased pu
where pu.productId = p.productId and
year(pu.creationdate) = year(now())
)
order by price desc;
I'm struggling with a question that said "which city of customers watches the most number of movies? (based on the number of films rented)".
I am doing this using the Seikila sample database in MySQL. The city entity has no relationship with rental and customer entity, but there's a address entity contain address_id which is id-dependent to customer entity. Then, the address entity has an attribute called city_id which the city entity also have got. And the customer_id attribute linked both customer and rental entities.
Also, I have to calculate the total number of films each customer in each city have rented.
I have only done the join part (code updated):
select rental_id,cust.customer_id,city.city_id,city.city from rental as r
inner join customer as cust on r.customer_id=cust.customer_id inner join
address as a on cust.address_id=a.address_id inner join city as city on
city.city_id=a.city_id
I realized that I should add city_id to the table, so my question will be:
how to count the number of rows of an unique customer_id so that I can get the total numbers of film rented of in each city, and with a group by?
Use COUNT(*) to get the total number of movie rentals, and group it by city.
SELECT city.city, COUNT(*) AS total_rentals
FROM rental AS r
INNER JOIN customer AS cust on r.customer_id = cust.customer_id
INNER JOIN address AS a on cust.address_id = a.address_id
INNER JOIN city ON city.city_id = a.city_id
GROUP BY city.city_id
ORDER BY total_rentals DESC
LIMIT 1
If you also want to know the number of customers in that city, you can add COUNT(DISTINCT cust.customer_id) to the SELECT list.