Use mysql joins to count no of invoices of customers - mysql

My invoices table has orderId column which is a foreign key referencing orderId primary key column of orders table and orders table has customerId column which references to customerId primary key column of customers table.
A customer can have multiple orders but an order has only one invoice.
I want to count the no of invoices of each customer. Below is the query I tried:
SELECT customers.name, COUNT(*) as number_of_invoices
FROM invoices
JOIN orders
ON invoices.orderId = orders.orderId
JOIN customers
ON orders.customerId = customers.customerId;
But it is only returning me one customer and the count is of total count not invoices count of that customer.

Here is a solution for your problem:
SELECT customers.name, COUNT(*) as number_of_invoices
FROM invoices
INNER JOIN orders
ON invoices.orderId = orders.orderId
INNER JOIN customers
ON orders.customerId = customers.customerId
GROUP BY Customers.name;
Just add GROUP BY in your query in last to group count of invoices for each Customer.

If you just need to know the count of invoice for each customer. It can be done without JOIN. Since order and invoice has one-to-one mapping you can use below sql queries
select customerId ,count(orderId) as invoice_count from orders group by customerId

Related

Creating a percentage column on a table made from an inner join

I have two tables Orders and RMA. I wrote this command to return an inner join between the two tables. OrderID is the primary key of Orders and foreign key of RMA.
SELECT Orders.SKU, COUNT(*) AS Frequency
FROM Orders
INNER JOIN RMA ON Orders.OrderID = RMA.OrderID
GROUP BY Orders.SKU
ORDER BY COUNT(*) DESC;
This select statement returns a table with one column containing SKU values and one column containing the number of times each SKU value appears in the data. My goal is to create a third column that includes a percent that represents the frequency of each SKU value.
(disclaimer: I'm new to mysql, so if there's more information needed for this question, I am happy to provide it. Thanks!)
You must divide COUNT(*) with the total number of rows in RMA:
SELECT Orders.SKU,
COUNT(*) AS Frequency,
COUNT(*) / (SELECT COUNT(*) FROM RMA) AS percent
FROM Orders INNER JOIN RMA
ON Orders.OrderID = RMA.OrderID
GROUP BY Orders.SKU
ORDER BY Frequency DESC;

Select data from specific row of grouped and joined table in MySQL

I have two tables, customers and orders which are inner joined. A customer can have several orders associated with them. In my selection, I then group by customers.id. I need to select the most recent order of each customer, but also the amount of money spent in that order. Currently, I can select the most recent order_date but do not know how to select the amount in the same row as the order_date.
This is my current query:
SELECT
first_name,
last_name,
email,
MAX(order_date) AS recent_order,
amount -- this needs to select amount associated with recent_order
FROM customers
JOIN orders
ON customers.id = orders.customer_id
GROUP BY customers.id;
The query selects the most recent date, but does not select the amount associated with the most recent order_date.
Table declarations:
CREATE TABLE customers (
id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(100),
last_name VARCHAR(100),
email VARCHAR(100)
);
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
order_date DATE,
amount DECIMAL(8,2),
customer_id INT,
FOREIGN KEY(customer_id) REFERENCES customers(id)
);
I would recommend a correlated subquery in the where clause:
SELECT c.*, o.* -- or whatever columns you want
FROM customers c JOIN
orders o
ON c.id = o.customer_id
WHERE o.order_date = (SELECT max(o2.order_date)
FROM orders o2
WHERE o2.customer_id = o.customer_id
);
For performance, you want an index on orders(customer_id, order_date).
SELECT
first_name,
last_name,
email,
MAX(order_date) AS recent_order,
(SELECT amount FROM orders WHERE order_date = MAX(order_date) AND customers.id = orders.customer_id) as amount
FROM customers
JOIN orders
ON customers.id = orders.customer_id
GROUP BY customers.id;
OR
SELECT
first_name,
last_name,
email,
order_date AS recent_order,
amount AS recent_order_amount
FROM customers
JOIN orders
ON customers.id = orders.customer_id
GROUP BY customers.id
ORDER BY orders.order_date DESC;
Use this:
SELECT TOP 1
t1.first_name,
t1.last_name,
t1.email,
t2.order_date,
t2.amount
FROM customers t1
JOIN orders t2
ON t1.id = t2.customer_id
ORDER BY
t2.order_date
Add a GROUP BY t1.id if the intent is to return all rows with the most recent order_date. Omit this if every order is resented by a single row in orders. Note this will not sum the amounts. You will have to do that in code or else use a different query. Also note that performance of this query will be affected by configuration of indexes. This query may not be performant if order_date is not part of an index and the table contains a large data set.

Get the max column value for each unique ID

I have two tables, a customers and orders table.
The customers table contains a unique ID for each customer. It contains 1141 entries.
The orders table contains many entries with a customerID and a date.
I am trying to query my database and return a list of customers and the max(date) from the orders list.
SELECT *
FROM customers
INNER JOIN
(
SELECT CustomerID, max(date) as date
FROM orders
GROUP BY CustomerID
) Sub1
ON customers.id = Sub1.CustomerID
INNER JOIN orders
ON orders.CustomerID = Sub1.CustomerID
AND orders.date = Sub1.Date
However this query is returning 1726 rows instead of 1141 rows. Where is this getting extra from?
I think it's beacause ORDERS table contains same customerID multiple times, so when you join the table with CUSTOMERS, each CUSTOMER.id matches multiple rows of ORDERS.
The problem is that there are ties.
For a given customer, some place more than one order per day. So there's a possibility that occasionally some may have placed more than one order on the date that is their max date.
To fix this, you need to use MAX() or some column that is always unique in the Orders table (or at least unique within a given date). This is easy if you can depend on an auto-increment primary key in the Orders table:
SELECT *
FROM customers
INNER JOIN
(
SELECT CustomerID, max(orderid) as orderid as date
FROM orders
GROUP BY CustomerID
) Sub1
ON customers.id = Sub1.CustomerID
INNER JOIN orders
ON orders.CustomerID = Sub1.CustomerID
AND orders.orderid = Sub1.orderid
This assumes that orderid increases in lock-step with increasing dates. That is, you'll never have an order with a greater auto-inc id but an earlier date. That might happen if you allow data to be entered out of chronological order, e.g. back-dating orders.
;with cte as
(
select CustomerID, orderdate
, rn = row_number() over (partition by customerID order by orderdate desc)
from orders
)
select c.*, cte.orderdate
from customer c
join cte on cte.customerID = c.customerid
where rn =1 -- This will limit to latest orderdate

SQL: How select rows and minus from another table

how construct sql query to select rows from table "Product" and minus sum(pc) from another table "Order".
Here is schema.
Thanks!
Group your orders by the product to get the sum of the pc-column for the products.
Then join the sum onto your product table, subtract the sum of the orders from your pc-column in the product table.
SELECT
product.id_product,
(product.pc - ifnull(orders.amount, 0))
FROM
product
LEFT JOIN (
SELECT
id_product,
SUM(pc) AS amount
FROM
`Order`
GROUP BY
id_product
) AS orders ON orders.id_product = product.id_product

SQL summery queries

I am having trouble getting the correct answer. My results are returning the same amount for all fields.
Please keep in mind that I am a newbie to SQL
Write a SELECT statement that returns one row for each customer that has orders with these columns:
The email_address column from the Customers table
The sum of the item price in the Order_Items table multiplied by the quantity in the Order_Items table
The sum of the discount amount column in the Order_Items table multiplied by the quantity in the Order_Items table
Sort the result set in descending sequence by the item price total for each customer. 
This is my code
SELECT email_address,
SUM(item_price * quantity) AS item_price_total
SUM(discount_amount * quantity) AS discount_amount_total
FROM customers c JOIN order_items oi
GROUP BY email_address
Order BY item_price_total
You need a join condition to relate the two tables. Otherwise, you just get a full cross-product.
SELECT email_address,
SUM(item_price * quantity) AS item_price_total
SUM(discount_amount * quantity) AS discount_amount_total
FROM customers c JOIN order_items oi ON c.id = oi.customer_id
#^^^^^^^^^^^^^^^^^^^^^^^^
GROUP BY email_address
Order BY item_price_total
I'm just guessing the names of the columns that relate the two tables, you should replace them with the actual columns.