postgres query for sales projections - sql

=================
This is my query:
SELECT
SUM(sub_total) AS sales,
CASE WHEN (sub_total<100) THEN '0-99'
WHEN (sub_total>=100 AND sub_total<200) THEN '100-199'
WHEN (sub_total>=200 AND sub_total<300) THEN '200-299'
WHEN (sub_total>=300 AND sub_total<400) THEN '300-399'
WHEN (sub_total>=400 AND sub_total<500) THEN '400-499'
ELSE '500+'
END
AS product_sales_range
FROM order_item
GROUP BY sub_total
========================
It gives the ressult as:
sales product_sales_range
----- -------------------
10398.96 200-299
600 100-199
300 0-99
7699.78 300-399
6799.32 100-199
600 0-99
26599.24 500+
==========================================
I would like to get the result like this :
sales product_sales_range sales_increase_by_10% sales_increase_by_20%
----- ------------------- ------------------ ------------------
10398.96 200-299
600 100-199
300 0-99
7699.78 300-399
6799.32 100-199
600 0-99
26599.24 500+
============
Requirement:
Currently we have sales figures. Need to find out the sales projection as if the sales will be increased by 10%, 20%, 30% etc. Example: today the sales for product_sales_range (0-99) is 300. If the sales is increased by 10%, sales_increase_by_10% should be 330

Am I missing something, or do you just need to use:
SELECT SUM(sub_total) AS sales,
CASE WHEN (sub_total<100) THEN '0-99'
WHEN (sub_total>=100 AND sub_total<200) THEN '100-199'
WHEN (sub_total>=200 AND sub_total<300) THEN '200-299'
WHEN (sub_total>=300 AND sub_total<400) THEN '300-399'
WHEN (sub_total>=400 AND sub_total<500) THEN '400-499'
ELSE '500+'
END AS product_sales_range,
SUM(sub_total) * 1.1 AS sales_increase_by_10Percent,
SUM(sub_total) * 1.2 AS sales_increase_by_20Percent
FROM order_item
GROUP BY sub_total

Related

Calculating percentages per product using aggregate functions and group by

I have a table with 5 rows representing two different products. The columns include the product, sales, discount. I'm trying to calculate the percentage of sales per product that included a discount. The table looks like this:
product
sales
discount
1
10
0
1
10
5
2
20
10
2
20
0
2
20
10
My results should look like the below (which I know because I've calculated this in Excel):
product
perc_discount
1
50.00
2
66.67
For each of the two products we are calculating the count of sales with discount divided by the total count of sales, so for product 1 it would be (1/2)*100 = 50.
My SQL code looks like the below:
SELECT
product,
(SELECT COUNT(*) FROM sales WHERE discount >0)/COUNT(*)*100 AS perc_discount
FROM sales
GROUP BY product
However, the result I'm getting is:
product
perc_discount
1
150.0
2
100.0
It seems to be calculating the total count of discounted sales in the table and diving it by the count of each product and I can't seem to figure out how to change it. Any ideas on how I can improve this?
Thanks.
How about conditional sum?
SQL> select product,
2 round(sum(case when discount > 0 then 1 else 0 end) / count(*) * 100, 2) perc_discount
3 from sales
4 group by product;
PRODUCT PERC_DISCOUNT
---------- -------------
1 50
2 66,67
SQL>
So: add 1 for every discount row per product. Divide that sum with total number of rows per product (that's count). Round the result to 2 decimals (so that it looks prettier).
You can use conditional aggregation. For example:
select
product,
100.0 * count(case when discount <> 0 then 'x' end) / count(*) as perc_discount
from sales
group by product

Joining tables and aggregation/sub queries

I have 2 tables as show below.
Table1
Order ID
Item_code
Sales_Price
Qty_ordered
Total
Qty shipped
1000
111
10
5
$50
1
1000
222
20
10
$200
2
1000
333
30
15
$450
0
I have another table that stores only the details of how much was invoiced (i.e. how much we shipped)
Table2 (because we shipped only 10x1 and 20x2 = $50)
Order ID
Invoice_total
1000
$50
I wrote the following query,
select T1.Order_ID,
sum(T1.Qty_Ordered) as Qty_Ordered,
sum(T1.Total) as Total_Amt_ordered,
sum(T1.Qty_shipped) as Qty_Shipped,
sum(T2.Invoice_total)
from T1 join
T2 on T1.Order_ID = T2.Order_ID
This query gives me the following output, (It is adding $50 to all the rows of T1 Orders).
Order ID
Qty_ordered
Total
Qty shipped
Invoice_total
1000
30
$700
3
$150
Whereas now, I want my output to be as:
Order ID
Qty_ordered
Total
Qty shipped
Invoice_total
1000
30
$700
3
$50
(because we shipped only $50)
What changes should I make to my query?
I know I can just hard code it but my database has 1000's of orders and 1000's of Half shipped Orders. I want to keep track of Shipped $ (Invoiced $) for all the orders.
If I understand correctly, you want:
select T2.Order_ID, T2.Invoice_total,
sum(T1.Qty_Ordered) as Qty_Ordered,
sum(T1.Total) as Total_Amt_ordered,
sum(T1.Qty_shipped) as Qty_Shipped,
from T2 join
T1
on T1.Order_ID = T2.Order_ID
group by T2.Order_ID, T2.Invoice_total;
That is, you don't want to aggregate Invoice_total. You just want it to be a group by key.

Applying percent change based on unique identifier

I'm calculating margins from a sales table in SQL and I need to reduce sales amounts if there is a discount in a sale based on it's invoice number. For this sample a 25% discount is applied Invoice 123. The total sales amount for invoice 123 is $100.00 but there is a 25% discount applied to that amount. What I want to do is apply that 25% discount to all sales numbers for invoice 123 so I can get the actual revenue number.
Sample Data:
ID Type ProductType Amount
123 Sale Jeans 50.00
123 Sale T-Shirt 30.00
123 Sale Sock 20.00
123 Discount - 25% NULL -25.00
456 Sale Jeans 60.00
456 Sale T-Shirt 40.00
456 Sale Sock 70.00
Expected Result:
ID Type ProductType Amount Actual Amount
123 Sale Jeans 50.00 41.67
123 Sale T-Shirt 30.00 21.67
123 Sale Sock 20.00 11.67
123 Discount - 25% NULL -25.00 0.00
456 Sale Jeans 60.00 60.00
456 Sale T-Shirt 40.00 40.00
456 Sale Sock 70.00 70.00
I've tried creating a new column where I multiple the amount times the discount rate but I can't get the numbers correct because it needs to be applied to the invoice number each discount corresponds to.
I'd like to have a new column that shows the adjusted amount based on the discount rate and then the discount amount showing zero.
One way is to use window functions to calculate the sum of the negative values for an id divided by the number of non negative values for that id by CASE expressions as arguments to the functions. The result of the division can than be deducted from the price. Additionally use a CASE to get zero for the negative values.
SELECT t1.id,
t1.amount,
CASE
WHEN t1.amount <= 0 THEN
0
ELSE t1.amount
+ sum(CASE
WHEN t1.amount < 0 THEN
t1.amount
ELSE
0
END) OVER (PARTITION BY t1.id)
/
count(CASE
WHEN t1.amount >= 0 THEN
1
END) OVER (PARTITION BY t1.id)
END actual_amount
FROM elbat t1;
db<>fiddle

MS-Access : How to sum multiple values from different tables according to dates

I have two similar tables as follows
Table 1
Date Amount Tax
4/1/2016 1000 100
4/1/2016 2000 200
5/3/2016 1500 150
5/6/2016 1000 100
5/6/2016 3000 300
7/9/2016 2500 250
Table 2
Date Amount Tax
4/1/2016 1000 100
4/2/2016 3000 300
5/3/2016 1500 150
5/9/2016 4000 400
8/11/2016 3000 300
10/9/2016 2000 200
dates can be similar or different in both tables.
I want two queries.
First, a query which gives me sum of amount and tax from each date from both tables between required dates. Eg: Table 1 have 2 entries and table 2 have 1 entry for 4/1/2016. so the result should be as below (summing up all three entries)
Date Amount Tax
4/1/2016 4000 400
4/2/2016 3000 300
5/3/2016 3000 300
5/6/2016 4000 400
5/9/2016 4000 400
7/9/2016 2500 250
8/11/2016 3000 300
10/9/2016 2000 200
Second,a query which gives of sum of amount and tax for each month from both tables between required dates. Eg output as below
Date Amount Tax
4/2016 4000 400
5/2016 11000 1100
7/2016 2500 250
8/2016 3000 300
10/2016 2000 200
Query that have I have written till now( not working )
SELECT date, sum(Amount),sum(Tax)
From Table1
WHERE Date BETWEEN #04/01/2016# AND #12/31/2016#
UNION ALL
SELECT date, sum(Amount),sum(Tax)
From Table2
WHERE Date BETWEEN #04/01/2016# AND #12/31/2016#
GROUP BY Date
For first query, consider a union query derived table with outer query aggregation:
SELECT q1.[Date], SUM(q1.Amount) AS DayTotalAmt, SUM(q1.Tax) AS DayTotalTax
FROM
(SELECT [Date], Amount, Tax
FROM Table1
UNION ALL
SELECT [Date], Amount, Tax
FROM Table2
) AS q1
GROUP BY q1.[Date]
For second query, consider using first query as a source with another outer query layer that runs a WHERE filter with month/year aggregation:
SELECT Format(q2.Date, "M/YYYY"), SUM(q2.DayTotalAmt) AS MonthTotalAmt,
SUM(q2.DayTotalTax) AS MonthTotalTax
FROM
(SELECT q1.[Date], SUM(q1.Amount) AS DayTotalAmt, SUM(q1.Tax) AS DayTotalTax
FROM
(SELECT [Date], Amount, Tax
FROM Table1
UNION ALL
SELECT [Date], Amount, Tax
FROM Table2) AS q1
GROUP BY q1.[Date]
) AS q2
WHERE q2.Date BETWEEN CDate("4/1/2016") AND CDate("12/31/2016")
GROUP BY Format(q2.Date, "M/YYYY")
Or if you save first query:
SELECT Format(q.Date, "M/YYYY"), SUM(q.DayTotalAmt) AS MonthTotalAmt,
SUM(q.DayTotalTax) AS MonthTotalTax
FROM Query1 q
WHERE q.Date BETWEEN CDate("4/1/2016") AND CDate("12/31/2016")
GROUP BY Format(q.Date, "M/YYYY")

How to join tables based on the dates

COMMISSION table
PRODUCT_ID DATE COMMISSION
1 20110101 27.00
1 20120101 28.00
1 20130705 30.00
2 20110101 17.00
2 20120501 16.00
2 20130101 18.00
...
ORDER table
PRODUCT_ID DATE PRICE
1 20110405 2500
2 20130402 3000
2 20130101 1900
Desired output
PRODUCT_ID DATE PRICE COMMISSION
1 20110405 2500 27.00
2 20130402 3000 16.00
2 20130101 1900 18.00
Commission table records commission % based on the product id and date.
Order table is basically a record of orders placed on a particular date,
I'd like to join two tables and bring the appropriate commission based on the date of the order. For example, you can see that the first order's commission is 27.00 as the date for the product_id 1 falls between 20110101 and 20120101.
How do I do this? Seems like a simple 1 to n relationship but I can't figure it out.
Try
SELECT o.*,
(
SELECT TOP 1 commission
FROM commission
WHERE product_id = o.product_id
AND date <= o.date
ORDER BY date DESC
) commission
FROM [order] o
Here is SQLFiddle demo