How do we find which customers placed orders with items made in USA refer to image - sql

Which customers placed orders with items made inside the USA?
SELECT DISTINCT, WHERE, Temporary Table, Subquery
tables to refer

I would use exists with a correlated subquery that follows the relationships like customer > order > order_item > product > supplier and filters on US suppliers:
select c.*
from customer c
where exists (
select 1
from order o
inner join order_item oi on oi.order_id = o.id
inner join product p on p.id = oi.product_id
inner join supplier s on s.id = p.supplier_id
where o.customer_id = c.id and s.country = 'USA'
)

Related

JOINS AND SUBQUERY

Question -
Display customer Id, name, and total number of orders, for orders handled by salesman Marshall, but only if customer name begins on General or ends on Electric. Exclude customers who placed a single order, but include customers without orders as well. Sort the result based on the total number of orders descending and then by name ascending.
Do not use LIKE operator and do not join 3 tables.
Questions output
Current Query
SELECT c.customer_id,
c.name,
Count(o.order_id) "# of Orders"
FROM customers c
left join orders o
ON c.customer_id = o.customer_id
WHERE Substr(c.name, 1, 7) = 'General'
OR Substr(c.name, -8) = 'Electric'
AND o.order_id IN (SELECT o.order_id
FROM orders o,
order_items oi
WHERE o.order_id = oi.order_id
AND o.salesman_id = (SELECT employee_id
FROM employees
WHERE
last_name = 'Marshall')
GROUP BY o.order_id
HAVING Count(customer_id) > 1)
GROUP BY c.customer_id,
c.name;
Database -
Not sure what I am doing wrong here.
That's a really contrived assignment... Here is one option:
select c.customer_id, c.customer_name, count(o.orderid) cnt
from customers c
left join orders o
on o.customer_id = c.customer_id
and (select last_name from employee e where e.employee_id = o.salesman_id) = 'Marshall'
where substr(c.name, 1, 7) = 'General' or substr(c.name, -8) = 'Electric'
group by c.customer_id, c.customer_name
having count(o.orderid) <> 1
The base idea is a left join. The where clause filters on the customer name - without like: you had that already.
To filter on the salesman name without an additional join, we use a correlated subquery in the on clause of the left join. There is no need to bring order_items, nor to select again from orders here.
Finally, the filtering on the order counts goes to the having clause.

T-SQL How to select all items without relationship in many-to-many situation?

Let's say there are 3 tables:
How can I show which CustomerId did not make an order for particular SupplierId
For example: SupplierId 2 did not get orders from CustomerId 1 and 5
So far my idea is to create a Table of all possible combinations of CustomerId/SupplierId and rows that have a match in the Orders table.
Is there a better way?
You can cross join the two referrential tables to generate all possible combinations, and use not exists to filter on those that do not exists in the bridge table:
select c.customerId, s.supplierId
from customers c
cross join suppliers s
where not exists (
select 1
from orders o
where o.customerId = c.customerId and o.supplierId = s.supplierId
)
You can also do this with an anti-left join:
select c.customerId, s.supplierId
from customers c
cross join suppliers s
left join orders o
on o.customerId = c.customerId and o.supplierId = s.supplierId
where o.customerId is null

Left join when there are lots of matched rows from right table

I have two tables.
Product(id, name)
LineItem(id, product_id, order_id)
Order(id, state)
Order can have many products. One product can belong to many orders at the same time.
I would like to select Products, which don't have orders with specific statuses(i.e. 1, 2).
My query is
SELECT products.id, products.price
FROM "products"
LEFT OUTER JOIN line_items ON line_items.product_id = products.id
LEFT OUTER JOIN orders ON orders.id = line_items.order_id AND orders.status IN (1, 2)
WHERE (products.price > 0) AND (orders.id IS NULL) AND "products"."id" = $1
GROUP BY products.id, products.price [["id", 11]]
11 is an id of a product, that should not appear to the result, but it does.
I would like to select Products, which don't have orders with specific statuses(i.e. 1, 2).
SELECT * FROM products p -- I would like to select Products
WHERE NOT EXISTS( -- , which don't have
SELECT *
FROM orders o -- orders
JOIN line_items li ON li.order_id = o.id
WHERE li.product_id = p.id
AND o.status IN (1,2) -- with specific statuses(i.e. 1, 2).
);
select p.id, p.name
from products p
join lineitem l on l.product_id = p.id
join `order` o on l.order_id = o.id
group by p.id, p.name
having sum(case when o.state in (1,2) then 1 else 0 end) = 0
The idea is to start with the products table and use left join to find orders with 1 or 2. If they don't exist, then you want the product:
select p.id, p.name
from product p left join
lineitem li
on li.product_id = p.id left join
orders o -- a better name for the table
on li.order_id = o.id and
o.state in (1, 2)
where o.id is null
group by p.id, p.name;

Fetch data from more than one tables using Group By

I am using three tables in a PostgreSql database as:
Customer(Id, Name, City),
Product(Id, Name, Price),
Orders(Customer_Id, Product_Id, Date)
and I want to execute a query to get from them "the customers that have have ordered at least two different products alnong with the products". The query I write is:
select c.*, p.*
from customer c
join orders o on o.customer_id = c.id
join product p on p.id = o.product_id
group by (c.id)
having count(distinct o.product_id)>=2
It throws the error:
"column "p.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: select c.*, p.*".
However if I remove the the p.* from select statement (assuming that I one does not want the products, only the customers), it runs fine. How can I get the products as well?
Update: Having ordered two or more products, a customer must appear on the output as many times as its product he has ordered. I want as output a table with 5 columns:
Cust ID | Cust Name | Cust City | Prod ID | Prod Name | Prod Price
Is it possible in SQL given that group by should be used? Shoul it be used on more than one columns on different tables?
Try this out :
SELECT distinct c.* ,p.*
FROM Customer c
JOIN
(SELECT o.customer_id cid
FROM Product P
JOIN Orders o
ON p.id= o.product_id
GROUP BY o.customer_id
HAVING COUNT(distinct o.product_id)>=2) cp
ON c.id =cp.cid
JOIN Orders o
on c.id=o.customer_id
JOIN Product p
ON o.product_id =p.id
I hope it solves your problem.
I think you can use following query for this question -
SELECT C1.*, p1.*
FROM Customer C1
JOIN Orders O1 ON O1.Customer_Id = C1.Id
JOIN Product P1 ON P1.Id = O1.Product_Id
WHERE C1.Id IN (SELECT c.Id
FROM Customer c
JOIN Orders o ON o.Customer_Id = c.Id
GROUP BY (c.Id)
HAVING COUNT(DISTINCT o.Product_Id) >= 2)

Joining on a group by

Lets say that I have three tables, customers, orders and orderDetails.
I'm doing this:
SELECT orders.ordersId, sum(orderDetails.total)
FROM orders
LEFT OUTER JOIN orderDetails ON orders.ordersId = orderDetails.ordersId
GROUP BY orders.ordersId
But lets say the orders table contains customersId. How do I join on the customers table so that I can also add the customer's name to the fields selected?
Thanks,
Barry
SELECT orders.ordersId, sum(orderDetails.total), customer.name
FROM orders
LEFT OUTER JOIN orderDetails ON orders.ordersId = orderDetails.ordersId
LEFT OUTER JOIN customer on customer.customerid = orders.customerid
GROUP BY orders.ordersId , customer.name
Try that out or something similar.
you can do it this way, which will let you get more than customer name if needed:
SELECT o.ordersId, o.orderTotal, c.customername, c.(other customer data)
FROM
(
SELECT orders.ordersId
, sum(orderDetails.total) as orderTotal
, orders.customersid
FROM orders
LEFT OUTER JOIN orderDetails
ON orders.ordersId = orderDetails.ordersId
GROUP BY orders.ordersId, orders.customersid
) o
LEFT JOIN customers c
ON o.customersid = c.customersid