SQL total amount where deposits are added and withdrawls subtracted [closed] - sql

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
-------------------------------------------
| CustomerID | Action | Amount |
|-------------------------------------------|
| 111 | deposit | 100 |
| 111 | withdrawl | 25 |
| 222 | deposit | 500 |
| 222 | deposit | 100 |
| 333 | withdrawl | 100 |
| 333 | deposit | 100 |
-------------------------------------------
Write a query that for each customerID would display the total Amount for that customer, where Deposit Actions are added to the total and Withdrawls are substracted from total

Using a CASE WHEN, you can treat the AMOUNT column differently in calculation based on the value of another field(ACTION).
SELECT CUSTOMERID,
SUM(CASE WHEN ACTION = 'DEPOSIT' THEN AMOUNT
WHEN ACTION = 'WITHDRAWL' THEN -AMOUNT ELSE 0 END) AS TOTAL_AMOUNT
FROM
TABLE1
GROUP BY CUSTOMERID;

You can directly use IF - ELSE logic ( if withdrawl or other "there's only one alternative") to write a simple query by using DECODE pseudo-code :
select CustomerID "Customer ID", sum(decode(Action,'withdrawl',-Amount,Amount)) "Total Amount"
from inventory
group by CustomerID
order by CustomerID;
D e m o

Related

SQL Filter unique results

I am trying to get an SQL statement that will output a unique part number eg no duplicates
However I want the type as Purchased is the default and when there isnt a Purchased part it defults back to Manufactured. NOTE all parts can be purchased
The result I require is to only show unique part numbers
e.g. 1 to 10 and Purchased is the default Type
Table1
Part_number | Type | Cost
Part 1 | Manufactured | £1.00
Part 1 | Purchased | £0.56
Part 2 | Manufactured | £1.26
Part 2 | Purchased | £0.94
Part 3 | Manufactured | £0.36
Part 3 | Purchased | £0.16
Part 4 | Manufactured | £1.00
Part 4 | Purchased | £1.50
Part 5 | Manufactured | £1.65
Part 6 | Manufactured | £1.98
Part 7 | Manufactured | £0.15
Part 8 | Manufactured | £0.45
Part 9 | Manufactured | £1.20
Part 9 | Purchased | £0.80
Part 10| Manufactured | £1.00
This is the result I am hoping to get back
Part_number | Type | Cost
Part 1 | Purchased | £0.56
Part 2 | Purchased | £0.94
Part 3 | Purchased | £0.16
Part 4 | Purchased | £1.50
Part 5 | Manufactured | £1.65
Part 6 | Manufactured | £1.98
Part 7 | Manufactured | £0.15
Part 8 | Manufactured | £0.45
Part 9 | Purchased | £0.80
Part 10| Manufactured | £1.00
I have tried loads of different techniques but am not getting the result.
I am guessing that I will need to create temp tables that are filtered and then join the tables together but I really don't know.
Any help will be apricated
You could also just grab the first row in each group by sorting them. This would make it easier when there are other columns of data to bring back.
with data as (
select *, row_number() over (
partition by part_number
order by case when t.type = Purchased then 1 else 2 end) as rn
from t
)
select * from data where rn = 1;
If there are other types this would work as well although you would want to tweak it if there are more than two per part.
One method uses not exists. Assuming you have at most two rows per part:
select t.*
from t
where t.type = 'Purchased' or
(t.type = 'Manufactured' and
not (exists (select 1 from t t2 where t2.part_number = t.part_number and t2.type = 'Purchased')
)
);
There are other fun ways to handle this. For instance, an aggregation approach:
select part_number,
max(type) as type,
coalesce(max(case when type = 'Purchased' then cost end),,
max(cost)
) as cost
from t
group by part_number;

Query columns based on values of table

I'm new to DB and SQL so I don't know if there is anything new I need to try for this. I want to solve this table my senior has given to me:
Passbook(Table Name)
Date | Amount | Type
-----------------------------
14/3/19 | 48000 | Debit |
13/2/19 | 75000 | Credit|
9/7/19 | 65000 | Credit|
12/6/19 | 15000 | Debit |
Now I have to generate a query in this manner:
Month | Debit | Credit
------------------------------
13/2/19 | 0 | 75000
14/3/19 | 48000 | 0
12/6/19 | 15000 | 0
9/7/19 | 0 | 65000
Here my Passbook table value has become the columns for query and IDK how to generate it in this manner
Anyone help me do this please
for monthly sorting, I'm supposed to use ORDER BY clause, I suppose
Now I have to generate a query in that manner.
A basic pivot query should work here:
SELECT
Format(Month([Date])) AS Month,
SUM(IIF(Type = 'Debit', Amount, 0)) AS Debit,
SUM(IIF(Type = 'Credit', Amount, 0)) AS Credit
FROM yourTable
GROUP BY
Format(Month([Date]));
If you instead want date level output, then aggregate the by the Date column directly.

Remove row values and convert into single column value

I have a stored procedure returning a table that looks like this:
ID | Type | Price | Description
-------------------------------
7 | J | 50.00 | Job
7 | F | 20.00 | Freight
7 | P | 30.00 | Postage
7 | H | 5.00 | Handling
I would like it to return the table like this:
ID | Type | Price | Description | FreightPrice
-----------------------------------------
7 | J | 50.00 | Job | 20.00
7 | P | 30.00 | Postage | 20.00
7 | H | 5.00 | Handling | 20.00
Is there a way that I can use a query such as:
SELECT * FROM Temp WHERE Type = 'F'
but return the 'Freight' row as a column instead with just the 'Price' value?
From what I have seen it appears that I may need to use the PIVOT operator to achieve this but that seems overly complex. Is there a way that I could achieve this result using a CASE or IF expression?
Based on the data you provided, there is one row having the description value: "Freight". Assuming this is the case, then try:
select ID,Type,Price,Description,
FreightPrice = (select Price
from mytable
where Description = 'Freight')
from mytable
where Description <> 'Freight'
If the Freight row is always moved to the right you can hard code this logic (assuming it's always a single row), as in:
select
id,
type,
price,
description,
(select price from t where description = 'Freight') as freightprice
from t
where description <> 'Freight'
Note: this query will crash if your table has more than one row for Freight.

Access 2016 & SQL: Totaling two columns, then subtracting them

Say I have a MoneyIN and a MoneyOUT column. I wish to total these entire columns up so I have a sum of each, then I wish to subtract the total of the MoneyOUT column from the total of the MoneyIN column. I also want to display a DateOF column and possibly a description (I think I can do that by myself).
This would be the original database where I get my information from:
+-------------+------------------+---------+----------+-----------+
| Location ID | Location Address | Date Of | Money In | Money Out |
+-------------+------------------+---------+----------+-----------+
| 1 | blah | date | 10.00 | 0.00 |
| 2 | blah | date | 2,027.10 | 27.10 |
| 2 | blah | date | 0.00 | 2000.00 |
| 1 | blah | date | 0.00 | 10.00 |
| 3 | blah | date | 5000.00 | 0.00 |
+-------------+------------------+---------+----------+-----------+
I would like to be able to type in a location ID and then have results show up (in this example I type 2 for the location)
+---------+----------+-----------+------+
| Date Of | Money In | Money Out | |
+---------+----------+-----------+------+
| date | 2027.10 | 27.10 | |
| date | 0 | 2000 | |
| Total: | 2027.10 | 2027.10 | 0 |
+---------+----------+-----------+------+
I have tried other solutions (One of which was pointed out below), however, they don't show the sum of each entire column, they simply subtract MoneyOUT from MoneyIN for each row. As of now, I am trying to do this in a query, but if there is a better way, please elaborate.
I am extremely new to SQL and Access, so please make the explanation understandable for a beginner like me. Thanks so much!
This is a table referred to below.
+-------------+-------+----------+-----------+-----------+
| Location ID | Date | Money IN | Money Out | Total Sum |
+-------------+-------+----------+-----------+-----------+
| 1 | date | 300 | 200 | |
| 1 | date | 300 | 200 | |
| 1 | date | 300 | 200 | |
| 1 | total | 900 | 600 | 300 |
+-------------+-------+----------+-----------+-----------+
The following should give you what you want:
SELECT DateOf, MoneyIn, MoneyOut, '' AS TotalSum FROM YourTable
UNION
SELECT 'Total', SUM(MoneyIn) AS SumIn, SUM(MoneyOut) AS SumOut,
SUM(MoneyIn - MoneyOut) AS TotalSum FROM YourTable
Edit:
You do not need to alter very much to achieve what you want. In order to get Access to prompt for a parameter when running a query, you give a name for the parameter in square brackets; Access will then pop-up a window prompting the user for this value. Also this parameter can be used more than once in the query, without Access prompting for it multiple times. So the following should work for you:
SELECT DateOf, MoneyIn, MoneyOut, '' AS TotalSum
FROM YourTable
WHERE LocationID=[Location ID]
UNION
SELECT 'Total', SUM(MoneyIn) AS SumIn, SUM(MoneyOut) AS SumOut,
SUM(MoneyIn - MoneyOut) AS TotalSum FROM YourTable
WHERE LocationID=[Location ID];
However, looking at your table design, I strongly encourage you to change it. You are including the address on every record. If you have three locations, but 100 records, then on average you are unnecessarily repeating each address more than 30 times. The "normal" way to avoid this would be to have a second table, Locations, which would have an ID and an Address field. You then remove address from YourTable, and in its place create a one-to-many relationship between the ID in Locations and the LocationID in YourTable.
It's a little unclear exactly what you expect without sample data, but I think this is what you want:
SELECT DateOf, SUM(MoneyIN) - SUM(MoneyOut)
FROM YourTable
GROUP BY DateOf
This will subtract the summed total of MoneyOut from MoneyIn at each distinct DateOf
Updated Answer
A UNION will let you append a 'Totals' record to the bottom of your result set:
SELECT *
FROM (
SELECT CAST(DateOf as varchar(20)) as DateOf, MoneyIn, MoneyOut, '' as NetMoneyIn
FROM YourTable
UNION
SELECT 'Total:', SUM(MoneyIn), SUM(MoneyOut), SUM(MoneyIN) - SUM(MoneyOut)
FROM YourTable
) A
ORDER BY CASE WHEN DateOf <> 'Total:' THEN 0 ELSE 1 END, DateOf
Some notes.. I used a derived table to ensure that the 'Total' record is last. Also casted DateOf to a string (assuming it is a date), otherwise you will have issues writing the string 'Total:' to that column.

SQL Access Sum multiple columns [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
Given a table named OrderInfo like below, I would like to sum the quantity and price for each order.
Table:
OrderID | Cost | Qty
0001 | 1.1 | 1
0001 | 2.2 | 3
0001 | 3.3 | 2
0002 | 10 | 5
0003 | 4.5 | 1
0003 | 9.9 | 1
...
Result:
OrderID | Cost | Qty
0001 | 6.6 | 6
0002 | 10 | 5
0003 | 14.4 | 2
...
Attempt:
SELECT OrderID, Sum(Cost) AS TotCost, Sum(Qty) AS TotQty
FROM OrderInfo
GROUP BY OrderID
My end goal is to use the resulting table to get the average of each order, so if there is an easier way to get that without summing cost and qty, then that solution will be nice!
End Goal:
OrderID | Average
0001 | 1.1
0002 | 2.00
0003 | 7.2
To get the values you want, just divide your calculations:
SELECT OrderID, Sum(Cost) AS TotCost, Sum(Qty) AS TotQty,
Sum(Cost) / Sum(Qty) AS AvgPerUnit
FROM OrderInfo
GROUP BY OrderID;