grouping common results in sql - sql

I have a products table, with the fields product, category and cost, of type varchar, varchar and decimal.
I then have a sales table, with the fields client, productname, quantity, cost, and saledate, of type varchar, varchar, int, decimal and date.
I want to show all of the products sold for a month, say the current month.
However, I don´t want to show every sale individually. I want to automatically add all of one product together and show it as one row.
In the sales table, the cost for each sales record is already multiplied by the quantity.
So for example, to if 5 beers were purchased, it would returned as one row showing name as beers, quanity as 5, and cost as however much.
I need something like say:
Select product, cost from sales, WHERE sales.product=products.name
AND category='food' AND WHERE month(date_field) = month(getdate())
This should show all the sales for a certain category of product for the current month, but is there an easy way to "group" products together?
I would have to take into account the quantity field in the sales table, because one sale is not necessarily only one product
A hopefully clearer example, one sale record maybe for 2 beers for one client with a cost of 10, and another sales record may be to a different client with a quantity of 3 and cost of 15. I want just one record that would say for beer, 5 were sold and the total cost is 25.
I have no idea where to go from as far as I have gotten...

You are looking for something like
Select product, cost from sales,products WHERE sales.product=products.name
AND category='food' AND month(date_field) = month(getdate())
To get a listing of the items linked as you suggest according to the category in the products tables.
To get the summary by category you need something like:
Select category,SUM(Sales.Quantity),SUM(Sales.cost) from
sales,products WHERE sales.product=products.name
AND category='food' AND month(date_field) = month(getdate()) group by category
This will work but there is a lot to criticise in your database structure, specifically to link products by name as you do is not very reliable.

This question looks awfully familiar...
The answer is a SQL GROUP BY statement.
SELECT product, SUM(quantity) FROM sales s, products p WHERE product=p.name AND category='food' AND month(date_field)=month(getdate()) GROUP BY product
The SUM(quantity) above will tally up all the units sold of a particular product in the given month.

Use GROUP BY and COUNT

SELECT productname, cost, COUNT(*) AS cnt
FROM sales LEFT JOIN products ON sales.product = products.productname
WHERE category='food' AND month(date_field) = month(getdate())
GROUP BY productname

Related

Aggregate my quantity sum in a way that doesn't lead to the storeID repeating?

I am writing a SQL query that needs to show the total number of orders from each store. The issue I am running into, is that while I can figure out how to sum the orders by product and each product is only sold by one store, I can't figure out how to total the orders by store alone
This is the code I currently have
SELECT storeID AS [STORE], Product_ID
, SUM(quantity) AS [ORDERS BY STORE]
FROM Fulfillment, Store
GROUP BY storeID, Product_ID;
This line of code leads to a repeat of storeID in the results, where ideally, I would only want storeID to be included in the results once with the total quantity of all of Product_ID being included. I tried to remove Product_ID from the GROUP BY statement, but this resulted in the following error
Column 'Fulfillment.Product_ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I'm new to SQL and am trying to learn, so any help and advice is greatly appreciated
#ZLK is correct that if your goal is a total number of units ordered ("quantity") of any product, simply remove the [product_id] column from the SELECT and GROUP BY.
However, it appears that you're referencing two tables ("FROM Fulfillment, Store") and not specifying how those tables are joined, creating a cartesian join - all rows in one table will be joined to all rows in the other table. If the [storeID] and [quantity] fields are available in the Fulfillment table, I recommend removing the Store table reference from the FROM clause (so "FROM Fulfillment" alone).
One last note: You mention that you want to count "orders". In some circumstances, an order may have multiple products and a quantity > 1. If your goal is the total number of "orders" regardless of the number of products or quantity of products on an order, you'll want to use "COUNT(DISTINCT orderID) as [Orders]" (where "orderID" is the reference to the unique order number).

What's the use of this WHERE clause

this is an answer to the question : We need a list of customer IDs with the total amount they have ordered. Write a SQL statement to return customer ID (cust_id in the Orders table) and total_ordered using a subquery to return the total of orders for each customer. Sort the results by amount spent from greatest to the least. Hint: you’ve used the SUM() to calculate order totals previously.
SELECT prod_name,
(SELECT Sum(quantity)
FROM OrderItems
WHERE Products.prod_id=OrderItems.prod_id) AS quant_sold
FROM Products
;
So there is this simple code up here, and I know that this WHERE clause is comparing two columns in two different tables. But since We are calculating the SUM of that quantity, why do need that WHERE clause exactly. I really couldn't get it. Why the product_id exactly and not any other column ( p.s: the only shared column between those two tables is prod_id column ) I am still a beginner. Thank you!
First you would want to know the sum for each product - so need to adjust the subquery similar to this:
(SELECT prod_id, Sum(quantity) qty
FROM OrderItems
group by prod_id
) AS quant_sold
then once you know how much for each product, then you can link that
SELECT prod_name,
(SELECT prod_id, Sum(quantity) qty
FROM OrderItems
group by prod_id
) AS quant_sold
FROM Products p
WHERE p.prod_id = quant_sold.prod_id
Run it without the where clause and compare the results. You'll learn a lot that way. specifically focus on two different product Ids ensuring they both have order items and quantities.
You have two different tables involved. There are multiple products. You don't want the sum of all orders on each product; which is what you would get without the where clause. So the where clause correlates the two tables ensuring you only SUM the quantity of each order item for each product between the tables. Personally, I'd use a join, sum, and a group by as I find it easier to read and I'm not a fan of sub selects in the select of another query; but that's me.
SELECT prod_name,
(SELECT Sum(quantity)
FROM OrderItems
WHERE Products.prod_id=OrderItems.prod_id) AS quant_sold
FROM Products
Should be the same as:
SELECT prod_name, Sum(coalesce(P.quantity,0))
FROM Products P
LEFT JOIN orderItems OI
on P.prod_id=OI.prod_id
GROUP BY Prod_Name
'Notes
the above is untested.
a left join is needed because all products should be listed and if a product doesn't have an order, the quantity would be zero.
if we use an inner join, the product would be excluded.
We use coalesce because you'd have a "Null" quantity instead of zero for such lines without an order item.
as to which is "right" well it depends and varies on different cases. each has it's own merits and in different cases, one will perform better than another, and in a different case, vice-versa. See --> Join vs. sub-query
As an example:
Say you have Products A & B
"A" has Order Item Quantities of 1 & 2
"B" has order item Quantities of 10 & 20
If we don't have the where clause every result record would have qty 33
If we have the where product "A" would have 3
product "B" would have qty 30.

SQL query to return a list of items including the records details, count and sum prices

I am a complete newbie to sql,
I have an access database table that contains a list of car part items including fields - partnumber, price, description, barcode etc- this table is used to temporarily store the details of a sale. It is a legacy system that does not include a qty ie for multiple items they are duplicate records in this temporary table.
I am trying to produce an "invoice" output in which I need to have The quantity of items (ie counts of duplicate items) list their description and part number and hopefully total each group of duplicate entries prices.
I have tried statements along the lines of
select partnumber, count(partnumber) as qty,
description, price, sum(price) as subtotal
from tblregister
group by partnumber
I know my syntax is way out just after some pointers as to how I achieve what I am after
Try adding the other non-aggregated fields in your select clause to the group by clause, like so:
select partnumber, count(partnumber) as qty, description, price, sum(price) as subtotal FROM tblregister group by partnumber, description, price

Select results get multiplied on joining

I'm using an SQL Server database which has Order table contains a foreign key called invoice_id, this attribute belongs to Invoice table. Also, I have another table called "Receiptwhich also includesinvoice_idandamount_paid` attributes.
Many items can be assigned to the same invoice (customer may make many orders at once), also many receipts can be assigned to the same invoice (customer may make different payments to the same invoice as for example they can pay 50% and then pay the rest later).
So the problem I'm facing is when I try to select the total paid amounts from the Receipt table taking the order_id as a condition, the result will be multiplied according to the number of orders that have the same invoice_id
For example, customer A placed three orders at once, each order cost is 100 USD, which should be 300 USD in the invoice and he already paid that invoice. Now if I query the Receipt table for the paid amounts, the result will be 900 USD (300 USD * 3 orders), which is obviously incorrect.
I'm stuck at this issue, I believe there are some mistakes in my database logic, so please provide me your suggestions to solve this problem and also what should do with the database if the logic is incorrect.
Below is the query i'm using to get the result:
select sum(r.amount_paid), o.invoice_id from RECEIPT r, INVOICE i, ORDER o
where r.invoice_id = i.invoice_id
and o.invoice_id = i.invoice_id
group by o.invoice_id;
Here's three answers to three slightly different questions you might ask of your database.
Amount paid per invoice
If you are trying to get the total amount paid per invoice, all you need is
SELECT SUM(Amount_Paid) Total_Paid,
Invoice_ID
FROM Receipt
GROUP BY Invoice_ID
Amount paid per order
If you want to know the total paid per order, this is not quite possible in your data model as you have described it. If a invoice has three orders on it, and the invoice is only partly paid, there is no way to tell which of the the orders is paid and which is not.
You need some additional data structure that indicates how payments are applied to orders within an invoice, e.g. an Allocation or Split table.
Amount paid on invoices that pertain to one or more orders
On the other hand, if you want to know how much payment has been received on invoices that contain one or more order IDs, you could write this:
SELECT SUM(Amount_Paid) Total_Paid,
Invoice_ID
FROM Receipt
WHERE Invoice_ID IN (SELECT Invoice_ID
FROM Order
WHERE Order_ID IN (1,2,3,4)) --Edit these IDs for your specific case
GROUP BY Invoice_ID
Notice none of the queries above required any joins, so no multiplying :)
Please, try this:
SELECT SUM(r.amount_paid), r.invoice_id FROM RECEIPT r
JOIN INVOICE i ON r.invoice_id = i.invoice_id
JOIN ORDER o ON r.invoice_id = o.invoice_id AND r.order_id = o.order_Id
GROUP BY r.invoice_id;

GROUP BY clause with logical functions

I'm using Oracle 11g Application Express, and executing these commands within the SQL Plus CLI. This is for a class, and I cannot get past this problem. I don't know how to add the total quantity of the items on the orders - I get confused as I don't know how to take the SUM of the QUANTITY per ORDER (customers have multiple orders).
For each customer having an order, list the customer number, the number of orders
that customer has, the total quantity of items on those orders, and the total price for
the items. Order the output by customer number. (Hint: You must use a GROUP BY
clause in this query).
Tables (we will use):
CUSTOMER: contains customer_num
ORDERS: contains order_num, customer_num
ITEMS: contains order_num, quantity, total_price
My logic: I need to be able to calculate the sum of the quantity per order number per customer. I have sat here for over an hour and cannot figure it out.
So far this is what I can formulate..
SELECT customer_num, count(customer_num)
FROM orders
GROUP BY customer_num;
I don't understand how to GROUP BY very well (yes, I have googled and researched it for a bit, and it just isn't clicking), and I have no clue how to take the SUM of the QUANTITY per ORDER per CUSTOMER.
Not looking for someone to do my work for me, just some guidance - thanks!
select o.customer_num,
count(distinct o.order_num) as num_orders,
sum(i.quantity) as total_qty,
sum(i.total_price) as total_price
from orders o
join items i
on o.order_num = i.order_num
group by o.customer_num
order by o.customer_num
First thing:
you have to join the two tables necessary to solve the problem (orders and items). The related field appears to be order_num
Second thing:
Your group by clause is fine, you want one row per customer. But because of the join to the items table, you will have to count DISTINCT orders (because there may be a one to many relationship between orders and items). Otherwise an order with 2 different associated items would be counted twice.
Next, sum the quantity and total price, you can do this now because you've joined to the needed table.
This is also solved by using WHERE:
SELECT orders.customer_num, /*customer number*/
COUNT(DISTINCT orders.order_num) AS "num_orders", /*number of orders/c*/
SUM(items.quantity) as "total_qty", /*total quantity/c*/
SUM(items.total_price) as "total_price" /*total price/items*/
/* For each customer having an order, list the customer number,
the number of orders that customer has, the total quantity of items
on those orders, and the total price for the items.
Order the output by customer number.
(Hint: You must use a GROUP BY clause in this query). */
FROM orders, items
WHERE orders.order_num = items.order_num
GROUP BY orders.customer_num
ORDER BY orders.customer_num
;