How to make this query on PostgreSQL? - sql

I have three tables:
Customer table
Product Table
Customer_Product Table
I need to make query: Search for customers who bought a certain product (for example, name = "toilet paper") at least 2 times
I don't understand how.. I'm noob in databases.. Please help

You need aggregation :
select c.name
from customer c inner join
customer_product cp
on cp.customer_id = c.customer_id inner join
product p
on p.product_id = cp.product_id
where p.lable = 'toilet paper'
group by c.name
having count(p.lable) > 1;

Related

SQL Query join issue between two tables

I'm new to SQL and I need help with how to select two tables and display the data.
I want to get the Name from Products and Description and Bestbefore from the second table ProductDescription.
Products table:
Id
Name
Quantity
Price
ProductDescription:
Id
Description
BestBefore
ProductId
Here is my attempt:
SELECT Name
FROM Products
INNER JOIN ProductDescriptions Description, BestBefore;
You aren't using the correct syntax. All the columns you want to query should be in the select list. Additionally, you're missing a join condition:
SELECT Name, Description, BestBefore
FROM Products p
INNER JOIN ProductDescriptions pd ON p.Id = pd.Id
You need to chose the columns you want, then join the tables.
SELECT p.name, d.description, d.bestbefore
FROM products p
INNER JOIN productdescription d
ON p.id = d.id

Best way of excluding customers with a specific order

I'm running a pretty basic query. The issue is I'm trying to get results with all of our customers who never ordered product Y. The problem is, if I use a simple WHERE ProductColumn <> 'Product Y', it doesn't work because almost all of our customers have ordered other products.
Basically, I'm wondering how I could exclude on the customer level (instead of the order level) - if a customer has ordered Product Y, I don't want them showing up in my results at all.
Thanks.
You are probably looking for EXISTS().
If I want to find customers who have placed orders:
SELECT c.*
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customerid = c.customerID
AND productID = 'Y'
)
If I want to find customers who have not placed orders:
SELECT c.*
FROM customers c
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.customerid = c.customerID
AND productID = 'Y'
)
Try this:
select * from customers c
where not exists(select 1 from customers
where cutomer_id = c.customer_id
and productcolumn = 'product y')
This assumes you have 'customer_id' column (or at least some id column in your table).
Simple LEFT JOIN should work:
SELECT c.*
FROM customers c
LEFT OUTER JOIN orders o
ON o.customerid = c.customerID
WHERE o.ProductColumn <> 'Product Y'

How to express nested SELECTS as a simpler JOIN

I have three tables:
customers: id, name
transactions: id_customer, id_item
items: id, name
I want to write a simple query that will return the names of all customers who ordered an item with the name 'apple'
I know I can do something like:
SELECT
name
FROM
customers
WHERE id IN (SELECT
id_customer
FROM
transactions
WHERE id_item IN (SELECT
id
FROM
items
WHERE name = 'apple'))
This may not be too bad, but it seems convoluted and like there might be a more straightforward way to do this with a join?
Yes, it's definitely better to use a join in this case. Try this:
SELECT DISTINCT
A.name
FROM
customers A INNER JOIN
transactions B ON A.id = B.id_customer INNER JOIN
items C ON B.id_item = C.id
WHERE C.name = 'apple'
In this way, only customers who placed an order containing 'apple's will be shown.
Use Join case, this a best way to approach.
Select C.name from Customers C
Inner Join Transaction T on C.id = T.id_customer
Inner Join Items I on T.id_items = I.id
where I.name = "Apple"
Above query will return the names of all customers who ordered "Apple".

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)

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