Given the following tables:
• Clients (ClientId, Name, Surname, Age)
• Products (ProductId, Name, Price)
• Purchases (Purchaseld, Date, ClientId, Productid)
I need to write an SQL query that shows the quantity of purchases made by clients. It must only show the clients who made more than 1 purchase. The result should contain the following fields: Full name (i.e. "john rambo"), Quantity of purchases.
I have written this query but results are not coming correct
SELECT Concat(clients.name, clients.surname)
FROM clients
JOIN products
ON clients.name = products.name
JOIN purchases
ON products.productid = purchases.productid
GROUP BY clientid
HAVING Count(clientid) > 1
SELECT Concat(clients.name, ' ', clients.surname),
count(*) as number_of_orders
FROM clients
JOIN purchases
ON products.productid = purchases.productid
GROUP BY Concat(clients.name, ' ', clients.surname)
HAVING Count(clientid) > 1
As noted in the comments, your join to products doesn't make much sense - your asking to only return records where there's a product that matches a client's first name.
CONCAT will glue the two fields together (e.g. "JohnRambo")
It must only show the clients who made more than 1 purchase.
Your question has no mention of products, so there is no need for that in the query:
SELECT CONCAT(c.name, c.surname)
FROM clients c JOIN
purchases p
ON p.ClientId = c.ClientId
GROUP BY c.ClientId, CONCAT(c.name, c.surname)
HAVING COUNT(*) > 1 ;
Note that the ClientId presumably uniquely defines the clients -- not the names. So the ClientId should be part of the aggregation.
Related
I just started learning SQL now and trying to figure out this scenario:
We have 3 tables:
Clients (ClientID, Name, Surname, Age)
Products (ProductID, Name, Price)
Purchases (PurchaseID, Date, ClientID, ProductID)
What would be the best SQL query that will show the amount of purchases (total amount per client) made by clients?
It must only show the clients who made more than 1 purchase.
The result should contain the following fields: Full name, Quantity of purchases, Total amount.
I've got this query but it only joins two tables. How do I join the third table (Products.Price) as well and calculate the total amount per client?
SELECT CONCAT(IFNULL(Name,''),' ', IFNULL(Surname,'')) as FullName,
COUNT(purchaseId) as "Quantity of purchases"
FROM Purchases as P
INNER JOIN Clients as C
on P.ClientID = C.ClientID
GROUP BY C.ClientID,Name, Surname
HAVING COUNT(PurchaseId) > 1;
I would recommend that you use CONCAT_WS() to combine the first name. This handles NULL values more elegantly than your solution.
SELECT CONCAT_WS(c.Name, c.Surname) as FullName,
COUNT(*) as num_purchases,
SUM(pr.price) as total_price
FROM Clients c INNER JOIN
Purchases p
ON P.ClientID = C.ClientID INNER JOIN
Products pr
ON pr.ProductID = p.ProductID
GROUP BY CONCAT_WS(c.Name, c.Surname)
HAVING COUNT(DISTINCT p.PurchaseId) > 1;
Note the COUNT(DISTINCT) in the HAVING clause. This ensures that the clients have at least two purchases. If you only want clients with at least two products or purchases, then you can use COUNT(*) -- but your question is about purchases.
You can try below -
SELECT CONCAT(IFNULL(Name,''),' ', IFNULL(Surname,'')) as FullName,
COUNT(purchaseId) as "Quantity of purchases",sum(price) as totalamount
FROM Purchases as P
INNER JOIN Clients as C
on P.ClientID = C.ClientID
inner join Products p1 on p.productid=p1.productid
GROUP BY C.ClientID,Name, Surname
HAVING COUNT(PurchaseId) > 1
I am working on a theatre booking system in MySql (My first SQL project). I have three tables:
Production (contains Title, BasicTicketPrice),
Performance (PerformanceDate, PerformanceTime, Title)
Booking (Email of person who booked, PerformanceDate, PerformanceTime, RowNumber).
Each person booked tickets for two or three performances (using their email to book).
I need to to write a query which will display the prices paid for all booked seats and I need to output the RowNumber, Email of person who booked and the Calculated Price.
I understand that I need to join these tables and make the query display a temporary column called Calculated Price but I don't know how to calculate the price.
I tried this:
SELECT DISTINCT b.RowNumber, b.Email, pr.BasicTicketPrice
FROM booking b, production pr performance p
WHERE p.Title=b.PerfDate*b.PerfTime*b.RowNumber;
SELECT CONCAT (PerfDate, PerfTime, RowNumber) AS BookingID FROM booking;
SELECT RowNumber, Email, CONCAT(PerfDate, PerfTime, RowNumber) AS BookingID FROM booking;
SELECT RowNumber, Email, CONCAT((CONCAT(PerfDate, PerfTime, RowNumber) AS BookingID
FROM booking)BasicTicketPrice*BookingID);
SELECT RowNumber, Email, CONCAT(PerfDate, PerfTime, RowNumber) AS BookingID INTEGER
FROM booking;
SELECT RowNumber FROM booking
LEFT JOIN (SELECT Title FROM performance WHERE '2017-11-01 19:00:00' Email IS NULL);
But it didn't work.
Any suggestions? I will be grateful for any ideas.
Assuming:
One row in Bookings per booked seat
Title to be a suitable primary key for Production
PerformanceDate, PerformanceTime to be a suitable primary composite key for Performance
You'll be looking to join the three tables together as per the keys assumed above. It seems you wish to group the bookings together per performance, by the person booking the tickets - if so, you'll need to use an aggregate to show the seat numbers (I've used GROUP_CONCAT to delimit them), as well as to COUNT the tickets purchased and multiply by the ticket cost.
SELECT
b.Email, prod.Title, per.PerformanceDate, per.PerformanceTime,
GROUP_CONCAT(RowNumber) AS BookedSeats,
COUNT(RowNumber) * prod.BasicTicketPrice AS TotalCost
FROM Booking b
INNER JOIN Performance per
ON b.PerformanceDate = per.PerformanceDate
AND b.PerformanceTime = per.PerformanceTime
INNER JOIN Production prod
ON per.Title = prod.Title
GROUP BY
b.Email, prod.Title, per.PerformanceDate, per.PerformanceTime, prod.BasicTicketPrice
ORDER BY prod.Title, per.PerformanceDate, per.PerformanceTime;
Technically, we should include all non-aggregated columns in the GROUP BY, hence prod.BasicTicketPrice is listed as well.
I have the following 2 tables (showing only sum of the columns here):
CUSTOMER:id, fname, lname.
SALES_ORDER: id, cust_id, sales_rep.
And the id from CUSTOMER connects with the cust_id from SALES_ORDER.
What I need to do is: Return customer details + number of orders made by that customer, for customers that have had at least one order handled by employee number '129'. This is the query I tried:
SELECT customer.id, fname, lname, count(*)
FROM customer,
sales_order
WHERE customer.id = sales_order.cust_id
GROUP BY customer.id
HAVING sales_rep = 129;
This does indeed return customers that answer the above + the number of order they had...but upon browsing the DB I see there are other clients that weren't fetched by the query. What am I doing wrong?
Thanks!
What about this:
SELECT customer.id, fname, lname, count(*)
FROM customer,
sales_order
WHERE customer.id = sales_order.cust_id
GROUP BY customer.id
HAVING MAX(IIF(sales_rep = 129, 1, 0)) = 1;
The idea is to calculated the count, but show only these records, where at least on of the sales_rep is 129. We are using IIF (you can use CASE WHEN for older SQL Server versions) to check if a particular record is for the specific sales_rep and MAX to check for at least one such record.
If you do not want to use HAVING you can filter the rows using additional filtering criteria:
SELECT customer.id, fname, lname, count(*)
FROM customer
INNER JOIN sales_order
ON customer.id = sales_order.cust_id
WHERE customer.id IN
(
SELECT DISTINCT customer.id
FROM sales_order
WHERE sales_rep = 129
)
GROUP BY customer.id
The idea is to calculated the count for each customer and then using a WHERE clause to display only users you have at least one sales_rep = 129.
I'm working on this database for a pet clinic (learning exercise), and what I want to do is to get the SUM for the same column, but different relationships.
These are my tables (only listing attributes used in query):
customer (customer_id, customer_name)
employee (employee_id, first_name, last_name)
pet (pet_id, owner_id, pet_name)
performed_service (performed_services_id, visit_id, service_id)
visit (visit_id, customer_id, employee_id, pet_id, date)
service (service_id, name, cost)
This is the query that I've tried, which so far gets all the data that I want, but not the SUMS correctly, which I cannot seem to understand how to do (if at all possible). What I'm trying to do is fetch the sum for service.cost for each pets visit, and sum of service.cost for all the visits that the customer has had, later I'm going to add a where clause on the date, so that it only shows instances of the current date:
SELECT
customer.customer_name,
pet.pet_name,
visit.date,
CONCAT(employee.first_name, ' ', employee.last_name) AS 'Veterenarian',
performed_service.service_id,
service.name AS 'Treatment',
service.cost AS 'Price',
SUM(service.cost) AS 'Pet Total',
SUM(service.cost) AS 'Customer Total'
FROM visit
INNER JOIN customer
ON visit.customer_id=customer.customer_id
INNER JOIN employee
ON visit.employee_id=employee.employee_id
INNER JOIN pet
ON visit.pet_id=pet.pet_id
INNER JOIN performed_service
ON visit.visit_id=performed_service.visit_id
INNER JOIN service
ON performed_service.service_id=service.service_id
GROUP BY performed_service.performed_service_id
Any help would be appreciated!
I want to run a query that generates a revenue report for campaigns. There are 2 tables
members and payments.
members (id, campaign_code)
payments (id, member_id, amount)
I want to create a table that groups by campaign_code, ie in this format
campaign_code, member_count, total_revenue
I am putting all campaigns into an array and running this,
SELECT sum( amount ) AS amt
FROM (members
INNER JOIN payments
ON payments.member_id = members.id
)
WHERE campaign_code = 'XX'
and it is taking a LOT of time. Anyway to optimize this or do it in a single query?
As you said that you need aggregation for all campaign code, try this
SELECT m.campaign_code , count(p.member_id) AS member_count,
SUM( amount ) AS total_revenue
FROM members m, payments p
WHERE p.member_id = m.id
GROUP BY campaign_code;
Make sure to read on mysql group by function
payments (id, member_id, amount)
I want to create a table that groups by campaign_code, ie in this format
campaign_code, member_count, total_revenue
I am putting all campaigns into an array and running this,
select
m.Campaign_Code,
count( distinct p.member_id) as Members,
count(*) as PaymentEntries,
sum( p.amount ) as TotalRevenue
from
members m
join Payments p
on m.id = p.member_id
where
m.campaign_code = 'XX'
If you want all campaigns, just remove the WHERE clause. You mentioned in comments that the tables DO have indexes, but I would ensure that members table has index on campaign_code, and payments has index on member_id.
This query will give a count of distinct members who've contributed, total number of contributions (in case one or more members contributed multiple times), and the totals of all the contributions.
use
where campaing_code in ('XX','YY','ZZ','AA','BB')
and have an index on campaing_code