DB2 SQL, Calculate total on orders ready to ship - sql

I'm trying to calculate the total value or all orders where we have all items in stock required to fill the order. In the example below, I want to select only the total value of order 100 only, since there is not enough inventory to fill order 200.
+-------+------+-------------+--------------+-------+
| Order | Item | Qty Ordered | Qty In Stock | Price |
+-------+------+-------------+--------------+-------+
| 100 | A | 10 | 25 | 1.00 |
+-------+------+-------------+--------------+-------+
| 100 | B | 15 | 50 | 2.00 |
+-------+------+-------------+--------------+-------+
| 100 | C | 30 | 75 | 3.00 |
+-------+------+-------------+--------------+-------+
| 200 | A | 5 | 25 | 1.00 |
+-------+------+-------------+--------------+-------+
| 200 | B | 100 | 50 | 2.00 | * Not enough stock to fill
+-------+------+-------------+--------------+-------+
| 200 | C | 35 | 75 | 3.00 |
+-------+------+-------------+--------------+-------+

How about:
select o.id, sum(o.qty_ordered * o.price) as total_value
from orders o
where o.id not in (
select id from orders where qty_ordered > qty_in_stock
)
group by o.id

Related

SQL Group By and sum of other column

following is raw table
+--------------+---------------+----------+---------+-----------+
| CustomerName | InvoiceNumber | ItemRate | TaxRate | TaxAmount |
+--------------+---------------+----------+---------+-----------+
| A | 1 | 500 | 4% | 20 |
| B | 2 | 300 | 9% | 27 |
| B | 2 | 100 | 9% | 9 |
| B | 2 | 400 | 4% | 16 |
| C | 3 | 250 | 9% | 22.5 |
| C | 3 | 650 | 4% | 26 |
| D | 4 | 200 | 4% | 8 |
| D | 4 | 100 | 4% | 4 |
+--------------+---------------+----------+---------+-----------+
I want output like this:
+--------------+---------------+--------------+---------+-----------+
| CustomerName | InvoiceNumber | InvoiceTotal | TaxRate | TaxAmount |
+--------------+---------------+--------------+---------+-----------+
| A | 1 | 500 | 4% | 20 |
| B | 2 | 800 | 9% | 36 |
| B | 2 | 800 | 4% | 16 |
| C | 3 | 900 | 9% | 22.5 |
| C | 3 | 900 | 4% | 26 |
| D | 4 | 300 | 4% | 12 |
+--------------+---------------+--------------+---------+-----------+
I am having issue with sum of Invoice value when doing Group By.
I have to do group by with "TaxRate" to combine similar Taxes and along with it i want to include new column in result which shows Total for that perticular Invoice.
Invoice Total column should have sum of entire invoice, where as my current query is summing Total by tax group and not by entire invoice.
my query is:
Select CustomerName, InvoiceNumber, sum(itemrate) as InvoiceTotal, TaxRate, sum(TaxAmount)
from salestable group by customername,invoicenumber, Taxrate
Please help to resolve this.
Thanks
If I understand correctly, you want to sum itemrate over the invoice for each customer:
select CustomerName, InvoiceNumber,
sum(sum(itemrate)) over (partition by CustomerName, InvoiceNumber) as InvoiceTotal,
TaxRate,
sum(TaxAmount) as TaxAmount
from salestable
group by customername, invoicenumber, Taxrate
Try this-
WITH CTE AS
(
SELECT CustomerName,SUM(ItemRate) InvoiceTotal
FROM your_table
GROUP BY CustomerName
)
SELECT A.CustomerName,A.InvoiceNumber,B.InvoiceTotal,A.TaxRate,SUM(A.TaxAmount)
FROM your_table A
LEFT JOIN CTE B ON A.CustomerName = B.CustomerName
GROUP BY A.CustomerName,A.InvoiceNumber,B.InvoiceTotal,A.TaxRate
ORDER BY A.CustomerName,A.TaxRate DESC
Something like:
SELECT tab.CustomerName,
tab.InvoiceNumber,
it.InvoiceTotal,
tab.TaxRate,
SUM(tab.TaxAmount) AS TaxAmount
FROM tab
INNER JOIN (
SELECT InvoiceNumber, SUM(ItemRate) AS InvoiceTotal FROM tab GROUP BY InvoiceNumber
) it ON it.InvoiceNumber = tab.InvoiceNumber
GROUP BY tab.CustomerName, tab.InvoiceNumber, it.InvoiceTotal, tab.TaxRate
ORDER BY tab.CustomerName, tab.TaxRate DESC
See the associated fiddle.
Results:
A 1 500 4 20
B 2 800 9 36
B 2 800 4 16
C 3 900 9 22.5
C 3 900 4 26
D 4 300 4 12

SELECTing monthly order amounts and item subtotals in a single query with two tables

I have an Orders table in the form:
| id | service_fee_cents | grand_total_cents | created_at |
|----|-------------------|-------------------|---------------|
| 1 | 1400 | 10000 | Jan 21 2018 |
| 2 | 1000 | 10000 | Feb 16 2018 |
| 3 | 500 | 10000 | March 21 2018 |
| 4 | 500 | 10000 | March 20 2018 |
And an Items table in the form
| id | order_id | title | price_cents | quantity |
|----|----------|--------|-------------|----------|
| 1 | 1 | lorem | 2000 | 2 |
| 2 | 1 | ipsum | 2030 | 1 |
| 3 | 2 | pie | 4000 | 4 |
| 4 | 3 | cheese | 6000 | 2 |
| 5 | 3 | burger | 7000 | 1 |
| 6 | 4 | custar | 1000 | 1 |
And I'm trying to run a SQL query to get a result in the form
| month | total_service_fee | total_grand_total | total_subtotal |
|-----------|-------------------|-------------------|----------------|
|2017-11-01 | 42 | 1,610 | 610 |
|2017-12-01 | 30 | 19,912 | 1,912 |
|2018-01-01 | 179 | 1,413 | 413 |
|2018-02-01 | 165 | 2,910 | 910 |
|2018-03-01 | 1,403 | 10,727 | 1,727 |
I've managed to get the first three columns using this query:
SELECT
date_trunc('month', created_at)::date AS month,
SUM(service_fee_cents) / 100 AS total_service_fee,
SUM(grand_total_cents) / 100 AS total_grand_total
FROM orders
GROUP BY month ORDER BY month
How do I get the last one? In the app, I get the sum via the following Ruby code:
order_subtotal = order.items.map{|item| item.price * item.quantity}.reduce(:+)
Which basically takes all the order's items, multiplies price by quantity and adds the results.
This should be a good start:
SELECT Date_trunc('month', created_at) :: DATE AS month,
SUM(service_fee_cents) / 100 AS total_service_fee,
SUM(grand_total_cents) / 100 AS total_grand_total,
SUM(total_subtotal) / 100 AS total_subtotals
FROM orders o
join (SELECT order_id,
SUM(price_cents * quantity) total_subtotal
FROM items i
GROUP BY order_id) i
ON o.id = i.order_id
GROUP BY month
ORDER BY month
You can get there by just joining the Orders table to the Items table and generating a SUM of subtotals by month. This may however be a somewhat expensive query to run if there are thousands of items in each order like you said.
SELECT
date_trunc('month', created_at)::date AS month,
SUM(service_fee_cents) / 100 AS total_service_fee,
SUM(grand_total_cents) / 100 AS total_grand_total,
SUM(price_cents * quantity) / 100 AS sub_total
FROM Orders o
JOIN Items i ON i.order_id = o.id
GROUP BY month ORDER BY month
http://sqlfiddle.com/#!15/555a2/1

calculating total sale with different prices

So I have a table which I am using to store data for my documents. Now I want to calculate my sale over some period and let's say I have table like this now:
| productID | price | quantity |
| 30 | 15 | 5 |
| 30 | 15 | 3 |
| 20 | 13 | 2 |
| 20 | 13 | 3 |
| 30 | 12 | 4 |
| 30 | 16 | 1 |
| 15 | 1 | 2 |
| 10 | 3 | 5 |
So I need a SQL command that will multiply the price and quantity for every row separate (because as you can see, for some products I have different prices e.g. where product id is 30) and then sum all those values.
This will give you total sales for each product
SELECT productID,
Sum(Price * quantity) AS Total_sales
FROM yourtable
GROUP BY productID

Calculate percentage of revenue per month

I have the following underlying data:
+-------+-------+---------------+
| Order | Month | sqft produced |
+-------+-------+---------------+
| 1001 | 4 | 10.29 |
| 1001 | 6 | 4'367.66 |
| 1001 | 7 | 203.57 |
| 1001 | 8 | 294.61 |
| 1001 | 9 | 92.28 |
| 1001 | 10 | 34.47 |
| 1001 | 12 | 16.59 |
| 1002 | 1 | 1.74 |
| 1002 | 4 | 19.54 |
| 1002 | 7 | 5'552.21 |
| 1002 | 9 | 309.62 |
| 1002 | 10 | 24.15 |
| 1002 | 12 | 52.16 |
| 1003 | 5 | 807.45 |
+-------+-------+---------------+
Those are three orders and I want to split the revenue according to the percentage of sqft produced in each month.
The revenue table:
+-------+-----------+
| Order | Revenue |
+-------+-----------+
| 1001 | 1'135'465 |
| 1002 | 1'773'499 |
| 1003 | 172'633 |
+-------+-----------+
So the output of the query should look like this:
+-------+-------+------------------+
| Order | Month | Revenue produced |
+-------+-------+------------------+
| 1001 | 4 | 2'327.72 |
| 1001 | 6 | 988'017.67 |
| 1001 | 7 | 46'050.00 |
| 1001 | 8 | 66'644.36 |
| 1001 | 9 | 20'874.86 |
| 1001 | 10 | 7'797.53 |
| 1001 | 12 | 3'752.86 |
| 1002 | 1 | 517.82 |
| 1002 | 4 | 5'815.02 |
| 1002 | 7 | 1'652'314.97 |
| 1002 | 9 | 92'141.64 |
| 1002 | 10 | 7'186.94 |
| 1002 | 12 | 15'522.60 |
| 1003 | 5 | 172'633.00 |
+-------+-------+------------------+
I am struggling with a way of getting the underlying data in that format because I can't seem to be able to split it by month.
Getting the percentage via dividing the square footage over the sum of the square footage partitioned over the [Order] would get you what you are looking for:
select p.[Order],
[Month],
Revenue,
[sqft produced],
CAST([sqft produced] / SUM([sqft produced]) OVER(PARTITION BY p.[Order]) AS DECIMAL(10,5)) * 100 as sqft_percentage,
Revenue * CAST([sqft produced] / SUM([sqft produced]) OVER(PARTITION BY p.[Order]) AS DECIMAL(10,5)) as revenue_produced
FROM [Orders] p
INNER JOIN Revenue r
ON r.[Order] = p.[Order]
Let's call the first table sqft and the second revenues. To avoid reserved words, the first table column's names will be:
order_id, month_num, sqft_produced
The second:
order_id, total_revenue
The SQL for what you need goes something like this (this is for Oracle):
SELECT order_id, month_num, (sqft_produced / total_sqft * total_revenue) revenue_produced
FROM sqft INNER JOIN
(SELECT order_id, total_sqft, total_revenue FROM (
(SELECT order_id, sum(sqft_produced) total_sqft
GROUP BY order_id) sqfts INNER JOIN revenues ON sqfts.order_id = revenues.order_id)) totals
ON sqft.order_id = totals.order_id;
Step by step:
SELECT order_id, sum(sqft_produced) total_sqft
GROUP BY order_id;
This gets you total square feet produced by order.
(SELECT order_id, sum(sqft_produced) total_sqft
GROUP BY order_id) sqfts INNER JOIN revenues ON sqfts.order_id = revenues.order_id;
This gets you a table with total revenues and total square feet.
And then you join this table to your sqft table and divide the square feet produced each month by total square feet and multiply by total revenue, thus splitting the revenue proportionally to square feet.

how to adjust the sum() of a group using the sum() of a subgroup()

I am trying to get the Output shown in the third table below using the tables "Assets" and "Transactions".
I am trying to group by Cmpy, Acct and AssetID and get the Sum(cost). But each cost has to be adjusted from the Transactions table before being summed. Not sure how to do it.
Table: Assets
+----------+------+---------+--------+
| Cpny | Acct | AssetID | Cost |
+----------+------+---------+--------+
| 50 | 120 | 109 | 100.00 |
| 50 | 120 | 109 | 200.00 |
| 50 | 120 | 110 | 300.00 |
| 50 | 120 | 110 | 20.00 |
| 50 | 121 | 107 | 150.00 |
| 50 | 121 | 201 | 200.00 |
+----------+------+---------+--------+
Table: Transactions
+------+---------+--------+
| Cpny | AssetID | Amt |
+------+---------+--------+
| 50 | 109 | -50.00 |
| 50 | 110 | 50.00 |
| 50 | 110 | -20.00 |
| 50 | 201 | -50.00 |
+------+---------+--------+
OUTPUT
+------+------+--------+
| Cpny | Acct | Total |
+------+------+--------+
| 50 | 120 | 600.00 |
| 50 | 121 | 300.00 |
+------+------+--------+
This one should give you an accurate answer:
SELECT a.Cpny,
a.Acct,
SUM(a.Cost + ISNULL(t.Adjustment, 0)) AS Total
FROM Assets a
LEFT JOIN (SELECT Cpny,
AssetID,
SUM(Amt) AS Adjustment
FROM Transactions
GROUP BY Cpny, AssetID) t
ON t.Cpny = a.Cpny AND t.AssetID = a.AssetID
GROUP BY a.Cpny, a.Acct
Associated SQLFiddle here.
Essentially, SUM the adjustment amounts in the transactions table, then join this to the main results list, summing the cost plus the adjustment for each asset in each account.
If the "relationship" between Acct and AssetID values are 1 to many then you could use this query (which is not so efficient):
SELECT x.Cpny,x.Acct, SUM( ISNULL(x.Total,0) + ISNULL(y.Total,0) ) AS Total
FROM
(
SELECT a.Cpny,a.Acct,a.AssetID, SUM(a.Cost) AS Total
FROM dbo.Assets a
GROUP BY a.Cpny,a.Acct,a.AssetID
) x
LEFT JOIN
(
SELECT t.Cpny,t.AssetID, SUM(t.Cost) AS Total
FROM dbo.Transactions t
GROUP BY t.Cpny,t.AssetID
) y ON x.Cpny=y.Cpny AND x.AssetID=y.AssetID
GROUP BY x.Cpny,x.Acct;