SQL query to retrive data [closed] - mysql

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
For these relations:
Customer(CID, Name, City, State),
Order(OID, CID, Date), and
Product(PID, ProductName, Price)
LineItem(LID, OID,PID, Number, TotalPrice),
where CID is a customer id and is a key for Customer, OID is an order id and is a key for Order, and LID is a line item id and is a key for LineItem. In addition the attribute CID of Order is a foreign key referring to the CID of Customer, that is, for each CID c of Order there is exactly one tuple of Customer whose CID attribute is c. The OID of LineItem is a foreign key referring to the OID of Order. There are several line items for the same order, a line item refers to a product and contains the quantity ordered for the product.
What is the query for:
List the products bought by all the customers of 'mycity'
#Edit
This is what I've tried so far:
Select ProductName
from Product
where PID in (
select PID
from LineItem
where OID in(
Select OID
from Order
where CID in(
select CID from customer where city='mycity'
)
)
);
This query however will return all the products bought by all customers from mycity. And the question requires only those products that everyone from 'mycity' have bought.
Not sure how to implement "All in" condition
#Edit2: Finally solved it :) Can someone please verify??

SELECT ProductName FROM Product
INNER JOIN LineItem ON LineItem.PID=Product.PID
INNER JOIN `Order` ON Order.OID=LineItem.OID
INNER JOIN Customer ON Order.CID=Customer.CID
WHERE Customer.City='mycity'
I think this should work

This query is solved in 2 parts: Create a view and query that view
Create view hview as (SELECT distinct count(distinct Customer.CID) as
uniquecustomer, count(distinct Customer.name), product.pid, product.Productname
FROM myorder
INNER JOIN Customer ON myorder.CID = Customer.CID
INNER JOIN LineItem ON myorder.OID = LineItem.oid
INNER JOIN Product ON Product.PID = LineItem.PID
where Customer.city = 'mycity'
group by Product.PID);
select productname from product where pid in(
select PID from hview where uniquecustomer in( SELECT count(distinct Customer.CID)
FROM myorder
INNER JOIN Customer ON myorder.CID = Customer.CID
INNER JOIN LineItem ON myorder.OID = LineItem.oid
INNER JOIN Product ON Product.PID = LineItem.PID
where Customer.city = 'mycity'));
Logic Used: create a view of items with distinct owners from mycity.
Query that view to find items that have distinct owners equal to number of distinct customers in mycity. Every item that has a distinct number of owners equal to the number of distinct customers of mycity are the products that are bought by everyone in mycity.
*myorder is the table name I used instead of order since thats a reserve word.

Better version in a single query:
select p1.productname from Product p1, myorder s1, lineitem l1, customer c1
where l1.pid=p1.pid
and l1.OID=s1.oid
and c1.cid=s1.cid
and c1.city='mycity'
group by p1.ProductName
having count(distinct c1.cid)=(select count(1) from customer c2 where c2.city='mycity');

Related

count(distinct(col_name)) not working in my sql [duplicate]

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

Is this join possible in SQL?

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

MySQL - Marking duplicates from several table fields, as well as data from another table

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.

Using ORDER BY on an INNER JOIN SQL query

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;

SQL how to count total rows for each customer with group by?

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.