Join data from three related tables - sql

In Postgres I have the following 4 tables
user (
id,
name
);
order(
id,
user_id
)
service(
id,
name
);
order_to_service(
id,
order_id,
service_id
price
);
I want to write a query to see User name , amount of orders of this user and how much money he spend on all orders
Example:
name amount price
Albert 100 3200
This is my query
select u.name , count(o.user_id),sum(ots.price)
from orders o inner join users u on u.id=o.user_id
inner join order_to_service ots on ots.order_id = o.id
where(o.user_id is not null) group by u.name
This is my result:
"Аlbert";55;29978
Accodring to this result user with name Albert has 55 orders
But using this query
select count(*) from orders where user_id = (select id from users where name like 'Albert')
Result is 33
What's wrong with my first query?

If the relationship between Orders table and Order_to_service table is one to many, then you would need to sum up the price per order in Order_to_service table before joining with the Orders table. Try this:
select u.name , count(o.user_id),sum(ots.price_tot)
from orders o inner join users u on u.id=o.user_id
inner join ( select order_id, sum(price) as price_tot
from order_to_service
group by order_id ) ots
on ots.order_id = o.id
where (o.user_id is not null) group by u.name

Related

SQL Server Query Count Join Table

I have 2 tables are call Suppliers and Products, which products have SupplierID as foreign key.
My question is how to make a query that can show this result
Supplier Name | Total Products
--------------+---------------
Unilever | 20
Kalbe | 50
Jhonson | 70
My table structure
Suppliers => ID, Name
Products => ID, SupplierID, Brand, Price
This is what I tried:
SELECT COUNT(*) AS Total
FROM Products
GROUP BY SupplierID
select
s.Name as 'Supplier Name', count(p.ID) as 'Total Products'
from
Supliers as s
left outer join
Producsts as p on (s.Id = p.SupplierID)
group by
s.Name;
All you need in addition to your query is a sub-query to obtain the name:
SELECT COUNT(*) as Total
, (select Name from Supplier where ID = SupplierID) as [Supplier Name]
FROM Products
GROUP BY SupplierID
you can use left join by SuplierID + subquery for Products group by SuplierID to avoid multi slow query.
select T1.Name as Supplier Name
,T2.cnt as Total Product
from Supliers T1
left join (
select SuplierID,count(1) cnt
from Products
group by SuplierID
) T2 on T1.ID = T2.SuplierID

Query table columns from another table using the foreign key

I am trying to get customer email and phonenumber in orders table when I have the order id.
The structure of the schema is below with customer id in orders table:
orders
id
date
item
refid
customerFk
customers
id
name
email
phonenumber
when I try to retrieve the customers phonenumber or email table from the order refId in SQL Server using
select
from order a
where a.custtomerFK.email
I get this error
Cannot call method on bigints
Please assist with the proper query.
The proper syntax is:
SELECT o.date, o.item, o.refid c.Name, c.email, c.phonenumber
FROM orders o
LEFT JOIN customers c ON o.customerFk = c.id
ORDER BY o.date, o.item, c.name
You can use this if you have customers for each order
SELECT orders.date, orders.item, orders.refid
, customers.Name, customers.email, customers.phonenumber
FROM orders
INNER JOIN customers ON orders.customerFk = customers.id

Subquery "Finding customer who has the most purchases"

I'm having trouble creating a query with a sub query to find the one customer in my DB who has made the most purchases. I need to list his/her full name, product name, price and quantity. Here is what I have so far
select first_name ||' '|| last_name "FullName", pt.name p.price, sum(ps.quantity)
from customers c
join purchases ps on c.customer_id = ps.customer_id
join products p on p.product_id = ps.product_id
join product_types pt on p.product_type_id = pt.product_type_id;
I need to use these three tables
Customers Table
Customer_ID
First_Name
Last_Name
DOB
Phone
Purchases Table
Product_ID
Customer_ID
Quantity
Products Table
Product_ID
Product_Type_ID
Name
Description
Price
Product Types Table
Product_Type_ID
Name
I am confused as where I should place the sub query (in the select row, from, having or where clause), if the arithmetic function should be placed in the select outer query or sub query. I know there are Nested subqueries, Correlated subqueries, Multiple-column subqueries, Multiple-row subqueries, Single-row subqueries. By the way, I am trying to do this in Oracle.
Here is an image with my result, except I removed sum from quantity column. Also, updated link.
(http://i1294.photobucket.com/albums/b618/uRsh3RRaYm0nD/Capture100_zps1f951b07.jpg)
I'm sorry, I forgot to include a fourth table, as you can see there are two name columns, in products table and product type table. The difference is that in products table "Name" is the specific name of the product, as shown in my link. The product type "Name" column is the more general name of the product, such as books, dvds, cds, etc. I need to include the product type "Name column in my query not product's name column. Therefore, the end result should look something like this
FullName ProductTypeName Price Quantity
John Brown Book Sumof4books 4
John Brown DVD Sumof2DVDs 2
John Brown Magazine Sumof1Mag 1
Here's one way to do it. It uses an analytic function to order customers by the total quantity of purchases: row_number() over (order by sum(quantity) desc). If there's more than one person with the same quantity, this will pick out only one.
It then takes this customer id and joins the rest of the tables in the obvious way to get the break down by product type.
Select
c.FullName,
pt.name,
Sum(p.price * ps.quantity) price,
sum(ps.quantity) quantity
From (
Select
c.Customer_ID,
c.first_name ||' '|| c.last_name FullName,
row_number() over (order by Sum(Quantity) desc) r
From
Purchases ps
Inner Join
Customers c
On ps.Customer_ID = c.Customer_ID
Group By
c.Customer_ID,
c.first_name ||' '|| c.last_name
) c
Inner Join
Purchases ps
On c.Customer_ID = ps.Customer_ID
Inner Join
Products p
On ps.Product_ID = p.Product_ID
Inner Join
Product_Types pt
On p.Product_Type_ID = pt.Product_Type_ID
Where
c.r = 1
Group By
c.FullName,
pt.name
Example Fiddle
For the second problem (show the customer who has the highest quantity for each product type, together with what they've spent on that product type)
Select
c.FullName,
c.name,
c.price,
c.quantity
From (
Select
c.first_name ||' '|| c.last_name FullName,
pt.name,
sum(p.price * ps.quantity) price,
sum(ps.quantity) quantity,
row_number() over (partition by pt.name order by Sum(Quantity) desc) r
From
Purchases ps
Inner Join
Customers c
On ps.Customer_ID = c.Customer_ID
Inner Join
Products p
On ps.Product_ID = p.Product_ID
Inner Join
Product_Types pt
On p.Product_Type_ID = pt.Product_Type_ID
Group By
c.first_name ||' '|| c.last_name,
pt.name
) c
Where
c.r = 1
Example Fiddle
Here is the general idea. You can adapt it for your database tables.
select fred, barney, maxwilma
from bedrock join
(select max(wilma) maxwilma
from bedrock
group by fred ) flinstone on wilma = maxwilma
SELECT CLIENT.CLIENTNO, CLIENT.CNAME, SUM(PURCHASE.AMOUNT) AS AMOUNT
FROM CLIENT
INNER JOIN PURCHASE
ON CLIENT.CLIENTNO = PURCHASE.CLIENTNO
WHERE CLIENT.CLIENTNO IN (
SELECT CLIENTNO
FROM (
SELECT PURCHASE.CLIENTNO, SUM(PURCHASE.AMOUNT) AS AMOUNT
FROM PURCHASE
GROUP BY PURCHASE.CLIENTNO
ORDER BY AMOUNT DESC
)
WHERE ROWNUM = 1)
GROUP BY CLIENT.CLIENTNO, CLIENT.CNAME;
select first_name ||' '|| last_name "FullName",name,quantity from customers,purchases,products where products.product_id = purchases.product_id and purchases.customer_id = customers.customer_id order by quantity;
This is the query you want

Repeated elements counting for Sql datatables queries

I have 2 tables: an Order table and an orderDetails table.
I have written a inner join:
SELECT Order.id
FROM Order
INNER JOIN orderDetails
ON Order.id=orderDetails.id
I have got the output as:
id
100
100
100
101
101
From the above data, I want the count of each record output as:
id count
100 3
101 2
How would I do this?
Select OrderId , Count(*) as [Count]
from OrderDetials
Group By OrderId
OrderId will be a foreing key column referencing Order.Id column of Order Table
If your orderDetails.id references Order.id column This will be the query.
Select id , Count(*) as [Count]
from OrderDetials
Group By id
SELECT o.id, COUNT(*)
FROM Order o
JOIN orderDetails od ON o.id=od.id
GROUP BY o.id
You need to use the COUNT aggregate and the GROUP BY clause.
SELECT Order.id, COUNT(DISTINCT orderDetails.id)
FROM Order
INNER JOIN orderDetails ON Order.id=orderDetails.orderId
GROUP BY Order.id
It also looks like you need o alter the join condition slightly.
Use Group by
SELECT Order.id, count(*) as Count
FROM Order
INNER JOIN orderDetails
ON Order.id=orderDetails.id Group by Order.id

MySQL Query to find customers who have ordered two specific products

I'm having trouble coming up with a query that will find all customers who have purchased both PROD1 and PROD2.
Here's a pseudo-query that kind of looks like what I want to do: (obviously this wouldn't work)
SELECT COUNT(DISTINCT userid)
FROM TRANSACTIONS
WHERE product_id = 'prod1'
AND product_id = 'prod2'
So basically I'm trying to get a count of the number of distinct userids that have a transaction in the transactions table for both product_id 'prod1' and 'prod2'. Each transaction is stored in a row in the transactions table.
I do this type of query in the following way:
SELECT COUNT(DISTINCT t1.userid) AS user_count
FROM TRANSACTIONS t1
JOIN TRANSACTIONS t2 USING (userid)
WHERE t1.product_id = 'prod1'
AND t2.product_id = 'prod2';
The GROUP BY solution shown by #najmeddine also produces the answer you want, but it doesn't perform as well on MySQL. MySQL has a hard time optimizing GROUP BY queries.
You should try both queries, analyzing the optimization with EXPLAIN, and also run some tests and time the results given the volume of data in your database.
SELECT userid
FROM TRANSACTIONS
WHERE product_id in ('prod1', 'prod2')
GROUP BY userid
HAVING COUNT(DISTINCT product_id) = 2
(Added new options below using the additional information provided by the user)
Try
SELECT * FROM Customers WHERE
EXISTS (SELECT * FROM Purchases WHERE ProductID = 'PROD1' AND CustID = Customers.CustID)
AND
EXISTS (SELECT * FROM Purchases WHERE ProductID = 'PROD2' AND CustID = Customers.CustID)
Or
SELECT * FROM Customers WHERE
CustID IN (SELECT CustID FROM Purchases WHERE ProductID = 'PROD1')
AND
CustID IN (SELECT CustID FROM Purchases WHERE ProductID = 'PROD2')
Or
SELECT UserID FROM Transactions WHERE ProductID = 'PROD1'
AND EXISTS (SELECT * FROM Transactions WHERE UserID = T1.UserID
AND ProductID = 'PROD2')
Or
SELECT UserID FROM Transactions WHERE ProductID = 'PROD1'
AND UserID IN (SELECT UserID FROM Transactions WHERE ProductID = 'PROD2')
This is an Access answer based on the infamous Northwind sample db. You should be abe to translate that in mySql quite easily.
SELECT o.CustomerID, Sum([ProductID]='Prod1') AS Expr1, Sum([productid]='Prod1') AS Expr2
FROM Orders AS o INNER JOIN [Order Details] AS d ON o.OrderID = d.OrderID
GROUP BY o.CustomerID
HAVING (((Sum([ProductID]='Prod1'))<>0) AND ((Sum([productid]='Prod1'))<>0));
SELECT COUNT(DISTINCT userId)
FROM(
SELECT userId
FROM transactions
WHERE product = 'PROD1'
INTERSECT
SELECT userId
FROM transactions
WHERE product = 'PROD2');
The query creates two intermediate tables, one which contains userId of customer who bought PROD1 and another identical table for those who bought PROD2.
The intersection operator returns a table which contains only rows found in both previous tables, i.e those who bought both products.
Example for sakila db:
SELECT R.customer_id, GROUP_CONCAT(I.film_id)
FROM sakila.rental R
RIGHT OUTER JOIN sakila.inventory I ON R.inventory_id = I.inventory_id
WHERE I.film_id IN (22,44) GROUP BY R.customer_id HAVING COUNT(*) = 2