GET DATA FROM TXT SUM GROUP BY AND SUBTRACT - sql

Trying to get data from txt file which contains buys and sells like in the format below.
I want to group by items and subtract each other.
I made three queries like totalin and totalout and stock but when I subtract out from in, some items are missing which has not been sold.
This is the data table
+------+---------+--------+
| TYPE | ITEM | AMOUNT |
+------+---------+--------+
| BUY | APPLE | 100 |
| BUY | ORANGE | 100 |
| BUY | APPLE | 200 |
| BUY | ORANGE | 200 |
| SELL | APPLE | 50 |
| SELL | APPLE | 50 |
| SELL | ORANGE | 100 |
| SELL | ORANGE | 100 |
| BUY | COCONUT | 50 |
| SELL | BANANE | 30 |
+------+---------+--------+
I want this output
+---------+--------+
| ITEM | AMOUNT |
+---------+--------+
| APPLE | 200 |
| BANANE | -30 |
| COCONUT | 50 |
| ORANGE | 100 |
+---------+--------+
I made 3 queries for the result that i want, but unfortunately I am stuck.
Here is my queries
QUERY 1 TOTAL IN:
SELECT DATA.TYPE, DATA.ITEM, Sum(DATA.AMOUNT) AS TOTALIN
FROM DATA
GROUP BY DATA.TYPE, DATA.ITEM
HAVING (((DATA.TYPE)="BUY"));
QUERY 2 TOTAL OUT:
SELECT DATA.TYPE, DATA.ITEM, Sum(DATA.AMOUNT) AS TOTALOUT
FROM DATA
GROUP BY DATA.TYPE, DATA.ITEM
HAVING (((DATA.TYPE)="SELL"));
QUERY 3 STOCK:
SELECT DATA.ITEM, [BUY]![TOTAL_IN]-[SELL]![TOTAL_OUT] AS STOK
FROM (DATA INNER JOIN BUY ON DATA.ITEM = BUY.ITEM) INNER JOIN SELL ON DATA.ITEM = SELL.ITEM
GROUP BY DATA.ITEM, [BUY]![TOTAL_IN]-[SELL]![TOTAL_OUT];
How can I made a query which shows the rest as stock.
Many thanks.

You can sum in one go like:
SELECT ITEM,
Sum(iif(data.type = "BUY", AMOUNT, -AMOUNT)) AS Stock
FROM DATA
GROUP BY ITEM;

You can think of SELL as -ve and BUY as +ve Amount.
Then the query becomes as follows
select item
,sum(case when type='BUY' then Amount
when type='SELL' then -Amount
end) as Amount
from data_table
group by item

In MsAccess, you can apply an if-logic block using the iif function and run the query in one step as below.
SELECT item,
SUM(iif ([type] = "SELL", (-1 * Amount), Amount)) as amounts
FROM data
GROUP BY item

Related

Get distinct values and sum their respective quantities

I have a problem.
I have a result query with order numbers item numbers and different quantities for each item.
I want to distinct all item numbers and count all quantities for each specific item number.
Here is an example table (Query output):
| OrderNo | ItemNo | Qty |
--------------------------------
| XY123 | 3000 | 4 |
| XY123 | 2000 | 2 |
| ZZ999 | 3000 | 6 |
| ZZ999 | 1000 | 3 |
| PP333 | 1000 | 5 |
The distinct values for all sold items with their item numbers would be:
1000 -> Count/Sum the Qty
2000 -> Count/Sum the Qty
3000 -> Count/Sum the Qty
Result:
| ItemNo | QtyTotal |
-------------------------
| 1000 | 8 |
| 2000 | 2 |
| 3000 | 10 |
My problem is, when I DISTINCT the ItemNo, i dont know how to SUM their corresponding quantities before. I need some advice please.
You can use group by:
select ItemNo, sum(Qty) as QtyTotal
from QueryOutput q
group by ItemNo;
You can replace QueryOutput with a query that produces your example table.
Fiddle

Join logic between tables without an obvious join condition

I've got 2 tables, one with an area, actions and quantities, and the other with prices and the goal is to combine the two in a view
table1
areaid integer
bananaunits integer
kilometers_ran integer
dogecoins integer
areaid | bananaunits | kilometers_ran | dogecoin
1 | 0 | 1 | 10
2 | 4 | 2 | 100
table2
rateid integer
description text
cost_per_unit integer
rateid | description | cost_per_unit
1 | price per banana | 0.5
2 | price per kilometers run | 2
3 | price per doge | 1
The intended outcome is to have a view which has the fields as following:
areaid, rateid, description, cost_per_unit, units, combined_cost
areaid| rateid| description| cost_per_unit| units| total_cost
1 | 1 | price per banana | 0.5 | 0 | 0
1 | 2 | per kilometers run | 2 | 1 | 2
1 | 3 | price per doge | 1 | 10 | 10
2 | 1 | price per banana | 0.5 | 4 | 2
2 | 2 | per kilometers run | 2 | 2 | 4
2 | 3 | price per doge | 1 | 100 | 100
In other words, I need to present all the rates per area in individual rows. how to achieve this?
Edit: current query that doesnt work
select areaid, rateid, description, cost_per_unit, units, combined_cost from table1,table2
Since you don't have a joining key and you want a row for each of combination of the area and rates, you're basically looking for a CROSS JOIN also called cartesian product

Calculate total amount PGSQL

query which calculates the total amount in dollars of stolen goods for each month for restricted and neutral items.
I have 2 tables
first
| UPC | item | in_stock | price | ship_day | class |
1 | 101 | 'generator' | 16 | 5999 | '12-1-2065'| 'restricted'
2 | 102 | 'blank tape' | 30 | 3000 | '12-1-2065'| 'neutral'
second
| UPC | unit_stolen |
1 | 101 | 4 |
1 | 401 | 2 |
If I understand correctly, this is basically a join and group by:
select date_trunc('mon', f.ship_day) as yyyymm,
sum(f.price * s.unit_stolen) filter (where f.class = 'restricted'),
sum(f.price * s.unit_stolen) filter (where f.class = 'neutral')
from first f join
second s
on f.upc = s.upc
group by date_trunc('mon', f.ship_day)

Duplicate records upon joining table

I am still very new to SQL and Tableau however I am trying to work myself towards achieving a personal project of mine.
Table A; shows a table which contains the defect quantity per product category and when it was raised
+--------+-------------+--------------+-----------------+
| Issue# | Date_Raised | Category_ID# | Defect_Quantity |
+--------+-------------+--------------+-----------------+
| PCR12 | 11-Jan-2019 | Product#1 | 14 |
| PCR13 | 12-Jan-2019 | Product#1 | 54 |
| PCR14 | 5-Feb-2019 | Product#1 | 5 |
| PCR15 | 5-Feb-2019 | Product#2 | 7 |
| PCR16 | 20-Mar-2019 | Product#1 | 76 |
| PCR17 | 22-Mar-2019 | Product#2 | 5 |
| PCR18 | 25-Mar-2019 | Product#1 | 89 |
+--------+-------------+--------------+-----------------+
Table B; shows the consumption quantity of each product by month
+-------------+--------------+-------------------+
| Date_Raised | Category_ID# | Consumed_Quantity |
+-------------+--------------+-------------------+
| 5-Jan-2019 | Product#1 | 100 |
| 17-Jan-2019 | Product#1 | 200 |
| 5-Feb-2019 | Product#1 | 100 |
| 8-Feb-2019 | Product#2 | 50 |
| 10-Mar-2019 | Product#1 | 100 |
| 12-Mar-2019 | Product#2 | 50 |
+-------------+--------------+-------------------+
END RESULT
I would like to create a table/bar chart in tableau that shows that Defect_Quantity/Consumed_Quantity per month, per Category_ID#, so something like this below;
+----------+-----------+-----------+
| Month | Product#1 | Product#2 |
+----------+-----------+-----------+
| Jan-2019 | 23% | |
| Feb-2019 | 5% | 14% |
| Mar-2019 | 89% | 10% |
+----------+-----------+-----------+
WHAT I HAVE TRIED SO FAR
Unfortunately i have not really done anything, i am struggling to understand how do i get rid of the duplicates upon joining the tables based on Category_ID#.
Appreciate all the help I can receive here.
I can think of doing left joins on both product1 and 2.
select to_char(to_date(Date_Raised,'d-mon-yyyy'),'mon-yyyy')
, (p2.product1 - sum(case when category_id='Product#1' then Defect_Quantity else 0 end))/p2.product1 * 100
, (p2.product2 - sum(case when category_id='Product#2' then Defect_Quantity else 0 end))/p2.product2 * 100
from tableA t1
left join
(select to_char(to_date(Date_Raised,'d-mon-yyyy'),'mon-yyyy') Date_Raised
, sum(Comsumed_Quantity) as product1 tableB
where category_id = 'Product#1'
group by to_char(to_date(Date_Raised,'d-mon-yyyy'),'mon-yyyy')) p1
on p1.Date_Raised = t1.Date_Raised
left join
(select to_char(to_date(Date_Raised,'d-mon-yyyy'),'mon-yyyy') Date_Raised
, sum(Comsumed_Quantity) as product2 tableB
where category_id = 'Product#2'
group by to_char(to_date(Date_Raised,'d-mon-yyyy'),'mon-yyyy')) p2
on p2.Date_Raised = t1.Date_Raised
group by to_char(to_date(Date_Raised,'d-mon-yyyy'),'mon-yyyy')
By using ROW_NUMBER() OVER (PARTITION BY ORDER BY ) as RN, you can remove duplicate rows. As of your end result you should extract month from date and use pivot to achieve.
I would do this as:
select to_char(date_raised, 'YYYY-MM'),
(sum(case when product = 'Product#1' then defect_quantity end) /
sum(case when product = 'Product#1' then consumed_quantity end)
) as product1,
(sum(case when product = 'Product#2' then defect_quantity end) /
sum(case when product = 'Product#2' then consumed_quantity end)
) as product2
from ((select date_raised, product, defect_quantity, 0 as consumed_quantity
from a
) union all
(select date_raised, product, 0 as defect_quantity, consumed_quantity
from b
)
) ab
group by to_char(date_raised, 'YYYY-MM')
order by min(date_raised);
(I changed the date format because I much prefer YYYY-MM, but that is irrelevant to the logic.)
Why do I prefer this method? This will include all months where there is a row in either table. I don't have to worry that some months are inadvertently filtered out, because there are missing production or defects in one month.

Relational database - adding products

I have the following situation, namely I need to make a database,
in which I will store products that the user added to breakfast,
lunch, midday meal and dinner ON A SPECIFIC DAY.
I have a problem with the construction of such a relational database.
I currently have this combination of two tables:
It seems to me that I need 3 tables here in which
the products themselves will be placed, but I have no idea how
I can combine these 3 tables to get queries
products depending on the type of meal (breakfast, lunch ..) and date (the day they were added)
Yes, you should have a Products table that should have the 5 last columns you are showing in your second table (Orders?). And remove them from the Orders table such that it only has the IDs referencing the Meal and Product and the Date.
Then you can do the following:
SELECT o.Date, m.Meal_Name, p.Product_Name, p.Carbohydrates,
p.Protein, p.Fat, p.Calories
FROM Orders o
INNER JOIN Meals m ON o.MealID = m.MealID
INNER JOIN Products p ON o.ProductID = p.ProductID
ORDER BY o.date, m.Meal_Name, p.Product_Name
Note that this will allow you to easly change the parameters (such as fat or Carbohydrates for a Product and have it appear in all records for that product.
While there is certainly plenty of room to interpretation here and you may only want to go so far in normalizing your data, I think a better option would be:
meals:
id | user_id | category_id | date
1 | 1 | 1 | 2019-09-03
meal_category
id | name
1 | breakfast
2 | lunch
3 | dinner
products
id | name | carbs | protein | fat | calories
1 | apple| 10 | 5 | 0 | 30
2 | cat | 0 | 20 | 5 | 80
3 | ham | 10 | 30 | 10 | 160
meal_products
meal_id | product_id
1 | 1
1 | 2
Bringing this together:
SELECT meals.id, meals.user_id, meal.date, meal_category.name, product.name, product.carbs, products.protein, products.fat, products.calories
FROM meals
INNER JOIN meal_category ON meals.category_id = meal_category.id
INNER JOIN meal_produts ON meals.id = meal_products.meal_id
INNER JOIN products ON meal_products.product_id = products.id
Which would yeild
+-----------+----------------+------------+---------------------+---------------+----------------+-------------------+---------------+-------------------+
| meals.id, | meals.user_id, | meal.date, | meal_category.name, | product.name, | product.carbs, | products.protein, | products.fat, | products.calories |
+-----------+----------------+------------+---------------------+---------------+----------------+-------------------+---------------+-------------------+
| 1 | 1 | 9/3/2019 | breakfast | apple | 10 | 5 | 0 | 30 |
| 1 | 1 | 9/3/2019 | breakfast | cat | 0 | 20 | 5 | 80 |
+-----------+----------------+------------+---------------------+---------------+----------------+-------------------+---------------+-------------------+