How to make it in one query - sql

I have the following relational table schema
Customer(customer_id, customer_name, customer_city)
Branch(branch_id, branch_name, branch_city)
Account(account_id, balance, customer_id, branch_id)
Question name every customer who has accounts in branches at least two different cities.
It is working for me the next query but only if I create a view first. Is there any other option to do it together?
My solution which works:
Create view Cust as select c.Customer_Name, c.customer_ID, b.branch_name, b.branch_city from Customer as c inner Join Account as a on c.customer_ID=a.customer_ID join Branch as b on b.branch_id=a.branch_id
SELECT * FROM Cust as c inner join Cust as c1 on c.CustomerID=c1.CustomerID and c.branch_city <> c1.branch_city

Here is one option using exists with an aggregate query
select c.*
from customer c
where exists (
select 1
from account a
inner join branch b on b.branch_id = a.branch_id
where a.customer_id = c.customer_id
group by c.customer_id
having min(b.branch_city) <> max(b.branch_city)
)

Related

Join in inside and outside subquery

I am working with 3 tables sales, customer & product where I want to get all columns from the sales table and customer_name, customer age from customer table and product_name, category from the product table in the same result set. There's a condition that I have to use 2 join operations where one join will be inside subquery and the other outside subquery.
Here's my query that's not working:
SELECT a.*,
b.customer_name,
b.age,
b.customer_id
FROM sales AS a
LEFT JOIN customer AS b on a.customer_id = b.customer_id
LEFT JOIN (SELECT product_id, product_name, category from product) as c
ON a.product_id = c.product_id
ORDER BY a.customer_id, b.customer_id;
Only the first join is working in this query.
select
a.*,
b.customer_name,
b.age,
b.customer_id ,
c.*
from sales as a
left join customer as b
on a.customer_id = b.customer_id
LEFT JOIN (SELECT product_id, product_name, category from product) as c
ON a.product_id = c.product_id
order by a.customer_id;
https://www.db-fiddle.com/f/wKbMaD6UF1v3a4KCXE7248/0

Find all customers who have an account at all branches located in Brooklyn

I have some tables:
"branch" table(branch_name, branch_city, assets)
"customer" table(customer_name, customer_street, customer_city)
"account" table (account_number, branch_name, balance)
"loan"table (loan_number, branch_name, amount)
"depositor"table (customer_name, account_number)
"borrower" table (customer_name, loan_number)
Now I want to find all customers who have an account at all branches located in Brooklyn. Here is my SQL for this problem. BUT I want to know how to use TABLE JOIN, and WITHOUT USING EXCEPT to solve this problem. CAN SOMEONE HELP ME ?????THANKS.
SELECT distinct S.customer_name FROM depositor as S
WHERE not exists (
(SELECT branch_name
FROM branch
WHERE branch_city = 'Brooklyn')
EXCEPT
(SELECT R.branch_name
FROM depositor as T, account as R
WHERE T.account_number = R.account_number and
S.customer_name = T.customer_name ))
I cannot come up with a way to do this using UNION. Your problem is to find a Customer that has ALL Branches in Brooklyn. Fundamentally there are two ways to go about that.
Solution 1 - Find the customers that do not not have all the branches in Brooklyn.
(Intentional double negative). In other words, find all customers that do not have at least one of the branches in Brooklyn, then take the rest.
This is what you are doing in your example. You take all the branches in Brooklyn EXCEPT the branches the customer has, if there are no Brooklyn branches remaining, then the customer has them all. You can do this another way using joins, though yours is probably more readable.
SELECT customer_name
FROM customer
WHERE customer_name NOT IN (
SELECT d.customer_name
FROM depositor d
INNER JOIN branch brooklyn ON brooklyn.branch_city = 'Brooklyn'
LEFT JOIN account a
ON d.account_number = a.account_number
AND brooklyn.branch_name = a.branch_name
WHERE a.account_number IS NULL )
Solution 2 - Find all the customers that have the same number of branches in Brooklyn as there are branches in Brooklyn.
In order to do this you will need to use a GROUP BY to get the count of Brooklyn branches per customer, you can then use this to compare to the total count of branches in Brooklyn.
SELECT d.customer_name
FROM depositor d
INNER JOIN account a ON d.account_number = a.account_number
INNER JOIN branch b ON a.branch_name = b.branch_name
WHERE b.branch_city = 'Brooklyn'
GROUP BY d.customer_name
HAVING COUNT(DISTINCT B.branch_name) = (
SELECT COUNT(branch_name)
FROM branch
WHERE branch_city = 'Brooklyn')
A UNION is used to combine two datasets. If your question was...
"Find all customers that have an account or a loan from a branch in Brooklyn."
...then you could use a UNION.
SELECT DISTINCT d.customer_name
FROM depositor d
INNER JOIN account a ON d.account_number = a.account_number
INNER JOIN branch b ON a.branch_name = b.branch_name
WHERE b.branch_city = 'Brooklyn'
UNION
SELECT DISTINCT l.customer_name
FROM borrower bo
INNER JOIN loan l ON bo.loan_number = l.loan_number
INNER JOIN branch b ON l.branch_name = b.branch_name
WHERE b.branch_city = 'Brooklyn'
Select A.customer_name
From depositor as A
Left join account as B
on B. account_number = A.account_number
group by A.customer_name
Having count(distinct(B.branch_name)) =
(select count(branch_name) from branch where branch_city = 'Brooklyn')
Assuming you want an answer to: "find all customers who have an account at any branch located in Brooklyn"
select c.*
from customer c
inner join depositor d
on c.customer_name = d.customer_name
inner join account a
on d.account_numver = a.account_number
inner join branch b
on a.branch_name = b.branch_name
where b.branch_city = 'Brooklyn'
If a customer can have more than one account or an account can have more than one branch, you will need to adjust the joins.

Display 2 columns from one table having max count in column 3 and display computed sum of values from another table

I've a customer table and purchases table,
need to show cname, cid with max(customer_visits) from customer table
and sum of total_purchases by customer in purchases table.
I'm doing something like this
select p.cid, c.cname, sum(p.total_price)
from customers c where exists
(select max(visits_made) from customers having visits_made=max(visits_made)
and cid=p.cid)
inner join purchases p on p.cid=c.cid
group by p.cid,c.cname
and
select p.cid, c.cname, sum(p.total_price)
(select max(visits_made) from customers c where c.cid=p.cid)
from purchases p
inner join customers c on c.cid=p.cid
group by p.cid,c.cname
What's going wrong with these queries?
Found the solution, had to include where clause after inner join :D
I think this is just an aggregation query:
select p.cid, c.cname, sum(p.total_price) as total_price,
max(visits_made) as visits_made
from purchases p inner join
customers c
on c.cid = p.cid
group by p.cid, c.cname;

SQL Query or Table Error?

So Im trying to find the total amount spent on Cuts and Products by each Customer
I don't know if my Query is Wrong or my entire Database Schema any ideas?
My Query
`Select First_Name, SUM(B.Cost), SUM(C.Cost)
FROM bookings A, cuts B, products C, customers D
Where A.Customer_ID= D.Customer_ID
AND A.Cut_ID = B.Cut_ID
AND A.Product_ID= C.Product_ID;`
My Database
`Table: bookings
Booking_N0, Customer_ID, Cut_ID, Product_ID, TimeTaken`
`Table: customers
Customre_ID, First_Name, Sex`
`Table: products
Product_ID, Products, Cost`
`Table: cuts
Cut_ID, Cut, Cost`
You should GROUP BY to SUM by each customer :
Select D.First_Name
, SUM(B.Cost)
, SUM(C.Cost)
FROM bookings A LEFT JOIN cuts B ON A.Cut_ID = B.Cut_ID
JOIN products C ON A.Product_ID = C.Product_ID
JOIN customers D ON A.Customer_ID = D.Customer_ID
GROUP BY D.First_Name;
Also, look forward using explicit join notation (FROM table1 t1 JOIN table2 t2 ON t1.field1 = t2.field2) instead of implicit join notation (FROM table1 t1, table2 t2 WHERE t1.field1 = t2.field2), because it is has more intuitive view (tables are listed near conditions on which they are joined).
Start using recommended JOIN / ON syntax for joining instead of using WHERE clause . You also need a GROUP BY clause
Select First_Name, SUM(B.Cost), SUM(C.Cost)
FROM bookings A
INNER JOIN cuts B
ON A.Cut_ID = B.Cut_ID
INNER JOIN products C
ON A.Product_ID= C.Product_ID
INNER JOIN customers D
ON A.Customer_ID= D.Customer_ID
GROUP BY First_Name
If you use aggregate function like SUM you have to add a group by clause
in your case:
...
AND A.Product_ID= C.Product_ID
GROUP BY First_Name

How to do a join with multiple conditions in the second joined table?

I have 2 tables. The first table is a list of customers.
The second table is a list of equipment that those customers own with another field with some data on that customer (customer issue). The problem is that for each customer, there may be multiple issues.
I need to do a join on these tables but only return results of customers having two of these issues.
The trouble is, if I do a join with OR, I get results including customers with only one of these issues.
If I do AND, I don't get any results because each row only includes one condition.
How can I do this in T-SQL 2008?
Unless I've misunderstood, I think you want something like this (if you're only interested in customers that have 2 specific issues):
SELECT c.*
FROM Customer c
INNER JOIN CustomerEquipment e1 ON c.CustomerId = e1.CustomerId AND e1.Issue = 'Issue 1'
INNER JOIN CustomerEquipment e2 ON c.CustomerId = e2.CustomerId AND e2.Issue = 'Issue 2'
Or, to find any customers that have multiple issues regardless of type:
;WITH Issues AS
(
SELECT CustomerId, COUNT(*)
FROM CustomerEquipment
GROUP BY CustomerId
HAVING COUNT(*) > 1
)
SELECT c.*
FROM Customer c
JOIN Issues i ON c.CustomerId = i.CustomerId
SELECT *
FROM customers as c
LEFT JOIN equipment as e
ON c.customer_id = e.customer_id --> what you are joining on
WHERE (
SELECT COUNT(*)
FROM equipment as e2
WHERE e2.customer.id = c.customer_id
) > 1
You can do it with a sub query instead of Joins:
select * from Customer C where (select Count(*) from Issue I where I.CustomerID = C.CustomerID) < 2
or whatever value you want