Check if row exists in other table - mysql

Given database schema:
Part( P#, PName, Producer, Year, Price)
Customer( C#, CName, Province)
Supply(S#, P#, C#, Quantity, Amount, Date)
How would I create a query to list names and provinces of the customers who did not buy any Apple products?
I have:
SELECT
b.cname,
b.province
FROM
part c,
customer b,
supply a
WHERE
c.PID = a.PID
AND b.CID = a.CID
AND c.producer != 'Apple'
However this returns all customers who bought something other than an Apple product. So I need to be able to compare to other records.

here, the customers who have not purchased Apple products
Select cname, Province
From Customer c
Where not exists
(Select * from Supply s
join Part p on p.pId = s.pId
Where CId = c.CId
and p.Producer = 'Apple')
and here select the customers who have only purchased Apple products:
Select cname, Province
From Customer c
Where exists
(Select * from Supply s
join Part p on p.pId = s.pId
Where CId = c.CId
and p.Producer = 'Apple')
and Not exists -- <- filter out the customers without an Apple product
(Select * from Supply n
join Part nap on nap.pId = n.pId
Where CId = c.CId
and nap.Producer != 'Apple')

Related

SQL query how to compare string

There are two tables:
Customers:
ID
Name
Surname
City
Orders:
OrderId
CustomerId
Purchase
Price
I'm trying to find customer id,name,surname where he hasn't Purchase "Pizza".
Any help to fix my query? I tried with cp.Purchase != "Pizza" but doesn't work
SELECT DISTINCT ID,FirstName,LastName
FROM Customers c
INNER JOIN Orders cp ON c.ID = cp.OrderID
ORDER BY c.ID
WHERE cp.Purchase LIKE '%Pizza%'
try this
select * from Customers where Id not in (
select CustomerId From Orders WHERE cp.Purchase LIKE '%Pizza%'
)
The right query is
SELECT DISTINCT c.ID, c.Name, c.Surname
FROM Customers c JOIN Orders o on c.ID = o.CustomerID
WHERE c.ID <> ALL (
SELECT c2.ID
FROM Customers c2 JOIN Orders o2 on c.ID = o2.CustomerID
WHERE o2.Purchase = 'Pizza')
This is because you are looking for who never bought a pizza, so you will select data of customers which ID never appear (<> ALL) in orders table in a record where a pizza was bought.
By the way, check also SQL base, try understand before getting the answer.

I'm getting an error when I try to use union

SELECT avg(Product.product_price)
From product
Where (
SELECT from customer
customer.city = "Tucson"
and Customer.cust_id = orders.cust_id
and Product.product_id = Orderline.product_id
)
group by product_name
UNION
SELECT sum(product.product_price)
From product
Where (
SELECT from customer
customer.city = "Tucson"
and Customer.cust_id = orders.cust_id
and Product.product_id = Orderline.product_id
)
group by product_name
I'm trying to display the average order from customers who order from tucson and the sum of the products going to tuscon
I have these tables with these (rows )orders (order_id, order_date, cust_id), product (product_id, product_name, product_price), orderLine (order_id, product_id, quantity), customer (cust_id, cust_name, street, city, state, zip) I need to 8. Show the average price and total price of products bought by customers from ‘Tucson’(Use Union) –
The problem is not with UNION - it's with the two queries you're attempting to UNION together. It looks to me like the AVG query should be something like:
SELECT avg(p.product_price)
From product p
INNER JOIN orderline ol
ON ol.product_id = p.product_id
INNER JOIN orders o
ON o.??????? = ol.???????
INNER JOIN customer c
ON c.cust_id = o.cust_id
WHERE c.city = 'Tuscon'
What's not clear from the code you posted is how the orders and orderline tables are to be joined - that is, what the common field(s) are in those tables. You'll need to fill that in.
Make similar changes to your SUM query.

Couple that have ordered the maximum of common products - SQL

I have trouble selecting the couple of customers that have ordered the maximum of common products.
Example :
Customer1 ordered products : a, b, c, z
Customer2 ordered products : a, c, d, g
Customer1 ordered products : g, h, z
Expected result : Customer1 | Customer2 | 2 (Number of common products ordered)
What I tried :
SELECT c.pid, c.cid, d.cid, count(c.pid)
FROM orders c JOIN orders d join
(SELECT a.cid, b.cid FROM customers a JOIN customers b ON b.cname != a.cname AND b.cname > a.cname) as subq
ON c.cid = a.cid and d.cid = b.cid
AND c.pid = d.pid group by c.pid;
This returns every couple of names :
select a.cname client_1, b.cname client_2
from customers a join customers b on b.cname != a.cname and b.cname > a.cname;
How can I get the max of common pids for a couple of cids ?
Tables :
customers (cid, cname, residence)
orders (pid, cid, odate, quantity)
products (pid, pname, price, origin)
Might not work in every RDBMS. Which one are you using?
select o1.cid, o2.cid, o1.pid, o1.cnt, o2.cnt
from (
select cid, pid, count(*) as cnt
, ROW_NUMBER() OVER(PARTITION BY cid, pid ORDER BY count(*) DESC) AS rn
from order
group by cid, pid
) as o1
join (
select cid, pid, count(*) as cnt
, ROW_NUMBER() OVER(PARTITION BY cid, pid ORDER BY count(*) DESC) AS rn
from order
group by cid, pid
) as o2
on o1.cid <> o2.cid
and o1.pid = o2.pid
where o1.rn = 1
and o2.rn = 1

Rewriting a query that has two sub queries using no sub queries

Given the database schema:
Part( PID, PName, Producer, Year, Price)
Customer( CID, CName, Province)
Supply(SID, PID, CID, Quantity, Amount, Date)
And the query:
Select cname, Province
From Customer c
Where exists (
Select *
from Supply s
join Part p on p.pId = s.pId
Where CId = c.CId
and p.Producer = 'Apple'
)
and Not exists (
Select *
from Supply n
join Part nap on nap.pId = n.pId
Where CId = c.CId
and nap.Producer != 'Apple'
)
How would I go about rewriting this query without the two sub queries?
You can use the LEFT JOIN/NULL pattern to find customers who haven't bought any non-Apple products. Then you can do this all with just joins. You'll have to join with Supply and Parts twice, once for finding Apple products, then again for excluding non-Apple products.
SELECT distinct c.name, c.province
FROM Customer AS c
JOIN Supply AS s1 ON s1.cid = c.cid
JOIN Parts AS p1 ON p1.pid = s1.pid
LEFT JOIN Supply AS s2 ON s2.cid = c.cid
LEFT JOIN Parts AS p2 ON p2.pid = s2.pid AND p2.producer != 'Apple'
WHERE p1.producer = 'Apple' AND p2.pid IS NULL
Notice that in the LEFT JOIN you put restrictions of the second table in the ON clause, not the WHERE clause. See Return row only if value doesn't exist for more about this part of the query.
You want customer who only bought Apple products?
One possible solution is based on conditional aggregation:
Select c.cname, c.Province
From Customer c
join
( -- this is not a Subquery, it's a Derived Table
Select s.CId -- assuming there's a CId in Supply
from Supply s
join Part p
on p.pId = s.pId
group by s.CId
-- when there's any other supplier this will return 1
having max(case when p.Producer = 'Apple' then 0 else 1 end) = 0
) as p
on p.CId = c.CId

Rewriting a query without using a subquery

Given the schema:
Part( PID, PName, Producer, Year, Price)
Customer( CID, CName, Province)
Supply(SID, PID, CID, Quantity, Amount, Date)
And the query:
Select Cname, Province
From Customer c
Where not exists
(Select * from Supply s
join Part p on p.PID = s.PID
Where CID = c.CID
and p.Producer = 'Apple')
How would I go about rewriting this query without a subquery? I've looked at other posts and most mention using a join however I'm confused as to how to approach it.
Something like this should work:
Select distinct Cname, Province
From Customer c
left join Supply s on s.CID = c.CID
left join Part p on p.PID = s.PID and p.Producer = 'Apple'
where p.PID is null
You can use left join
SELECT Cname, Province
FROM Customer c
LEFT JOIN Supply s ON c.id = s.id
JOIN Part p on p.PID = s.PID
WHERE s.Producer = 'Apple'
AND s.id is NULL;
Try the following.
Select Cname, Province
From Customer c
-- join whatever the table that you have common customer id
left join Supply s s.cid = c.cid
join Part p on p.PID = s.PID and p.Producer = 'Apple'
where s.cid is null