Let's have 4 simple tables:
TABLE region (id, name)
TABLE country (id, name, region_id)
TABLE organization (id, name, country_id)
TABLE person (id, name, organization_id)
I want to make a query, where I would have:
Region name
Person count for region
Country name
Person count for country
Organization name
Person count for organization
Person name
For instance:
Europe, 20, Slovakia, 2, University of Life, 1, Somebody
How can I make those counts in a effective way in MySQL?
I have a huge query, where I have inline selects for each count, but this is not at all efficient. I was considering sum with case, but I don't quite grasp the concept if I have thousands of organizations with different names...
SELECT r.name as region, count(DISTINCT r.id) as region_total,
c.name as city, count(DISTINCT c.id) as country_total,
o.name as organization, count(DISTINCT o.id) as organization_total,
COUNT(p.id) as person_total
FROM region r
JOIN country c
on r.id= c.region_id
JOIN organization o
ON c.id = o.country_id
JOIN person p
ON o.id p.organization_id
GROUP BY r.id, c.id, o.id
ORDER BY r.id, c.id, o.id
I dont see how you want to include a person name here
Related
I need to get the customer state, book name, order count and revenue from tables named order_line_items (contains the order quantity), orders (contains the revenue), customers (contains the state) and books (contains book name) . So far I have:
SELECT
YEAR(purchased_at) AS year_purchased,
COUNT(*) order_count,
COUNT(DISTINCT customer_id) customer_count,
CONCAT('$', FORMAT(SUM(total), 2)) AS revenue
FROM
orders
GROUP BY
year_purchased
ORDER BY
year_purchased;
the code above works fine but is not complete, when I add the rest of what I need I get a wrong total for count and revenue. This is giving me issues:
SELECT
YEAR(purchased_at) AS year_purchased,
COUNT(*) order_count,
COUNT(DISTINCT customer_id) customer_count,
CONCAT('$', FORMAT(SUM(total), 2)) AS revenue,
state,
collection
FROM
customers c
JOIN books
JOIN orders o ON c.id = o.customer_id
GROUP BY
year_purchased,
state,
collection
ORDER BY
year_purchased,
state,
collection LIMIT 4;
I'm still learning the MySQl.
This is the relational DBMS :
CUSTOMER (CustID, CustName, AnnualRevenue)
TRUCK (TruckNumber, DriverName)
CITY (CityName, Population)
SHIPMENT (ShipmentNumber, CustID, Weight, Year, TruckNumber, CityName)
Now, I have to formulate for these two queries:
Total weight of shipments per year for each city.
Drivers who drove shipments to London but not Paris.
These are the queries i have came up with:
1.
select sum(s.weight), s.year , c.city
from shipment s, city c
INNER JOIN CITY
on s.CityName = c.CityName
You are mixing and old way to JOIN table (which you should avoid because the joining columns are not explicitly stated and it is confusing for others):
FROM shipment s, city c
You should group columns in the select that are not aggregated (year, city). Also it is better to use an alias for the aggregated column (AS total_weight)
select sum(s.weight) AS total_weight, s.year , c.city
from shipment s
INNER JOIN CITY as c
on s.CityName = c.CityName
GROUP BY s.year, c.city
Try to solve the second query and come back if you have a problem.
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!
Let's say i have the following model:
Customer(customer_id (PK), firstName, lastName, email)
Item(item_id (PK), name, description)
Orders(orders_id (PK), customer_id (FK), item_id (FK), promotion_id (FK)),
Promotion(promotion_id (PK), date, gift_id (FK))
Gift(gift_id (PK), name, description)
Now, let's say that i have the following requirement:
Retrieve the list of all orders (not grouped by) from all customers and the name column from both the item and gift associated.
The difficult part is that the association table orders has a foreign key column to a one to many table (promotion) that, in his turn, has the foreign key to the gift;
I have the following query that worked, but i figure out that should have a more elegant way to approach the problem than doing a lot of joins like this:
select concat(c.firstName, ' ', c.lastName) as customerName,
i.name, g.name
from customer as c
left join orders as o on c.customer_id = o.customer_id
inner join item as i on o.item_id = i.item_id
inner join promotion as p on o.promotion_id = p.promotion_id
inner join gift as g on p.gift_id = g.gift_id;
How i could resolve the query in a more elegant way?
Thanks in advance!
I think this is perfectly elegant. Joins are very classy and often misunderstood.
You can drop the INNER keywords as joins are inner by default, and the AS keywords are optional; also because your column names are the same across the joins, you can simply use USING instead of ON:
SELECT CONCAT_WS(' ', c.firstName, c.lastName) customerName,
i.name, g.name
FROM customer c
LEFT JOIN orders o USING (customer_id)
JOIN item i USING (item_id)
JOIN promotion p USING (promotion_id)
JOIN gift g USING (gift_id)
Indeed, if those are the only columns having the same name across the joined tables one could go further and use NATURAL joins (although I don't like that as it hides what's going on if the schema changes):
SELECT CONCAT_WS(' ', c.firstName, c.lastName) customerName,
i.name, g.name
FROM customer c
NATURAL LEFT JOIN orders o
NATURAL JOIN item i
NATURAL JOIN promotion p
NATURAL JOIN gift g
I need to query the database by joining two tables. Here is what I have:
Table Town:
id
name
region
Table Supplier:
id
name
town_id
I currently have the following query which outputs all the Towns that belong to a given region:
SELECT id, name FROM Town WHERE region = 'North West';
Now I need to extend this query and create two further queries as follows:
Output the number of Suppliers for each Town
Output only the Towns that have 1 or more Supplier
I am using PHP for my scripts if that helps. I know I may be able to to get this data using PHP but in terms of performance it will probably be better if it is done in MySQL.
EDIT (27/07/10):
I now needs to extend this one last time - there is another table called Supplier_vehicles:
id
supplier_id
vehicle_id
A Supplier can have many Supplier_vehicles. The count (NumSupplier in this case) needs to now contain the total number of suppliers in a given town that have any of the given vehicle_id (IN condition):
SELECT * FROM Supplier s, Supplier_vehicles v WHERE s.id = v.supplier_id AND v.vehicle_id IN (1, 4, 6)
Need to integrate the above query into the existing JOIN query.
Count the number of suppliers.
SELECT t.id, t.name, count(s.id) as NumSupplier
FROM Town t
LEFT OUTER JOIN Suppliers s ON s.town_id = t.id
GROUP BY t.id, t.name
Only towns that have at least one supplier
SELECT DISTINCT t.id, t.name
FROM Town t
INNER JOIN Suppliers s ON s.town_id = t.id
And you are 100% correct, the best place for this is an SQL query.
SELECT t.id, t.name, count(s.id) as NumSupplier
FROM Town t
LEFT JOIN Suppliers s
[WHERE NumSupplier > 1]
GROUP BY t.id