Performing subtraction in SQL/finding the balance - sql

SQL table here: http://sqlfiddle.com/#!9/abe1da/9
Current Table:
Year
Month
Type
Accounts
Amount
2021
1
Actual
abc
20
2021
1
Actual
def
30
2021
1
Actual
ghi
40
2021
1
Actual
X
7
2021
1
Actual
Y
3
2021
1
Actual
final
105
Expected
Year
Month
Type
Accounts
Amount
2021
1
Actual
abc
20
2021
1
Actual
def
30
2021
1
Actual
ghi
40
2021
1
Actual
X
7
2021
1
Actual
Y
3
2021
1
Actual
final
105
2021
1
Actual
BALANCE
5
SQL Attempt
select year, month, type,
case when accounts in ('abc') then 'abc'
when accounts in ('def') then 'def'
when accounts in ('ghi') then 'ghi'
when accounts in ('X') then 'x'
when accounts in ('Y') then 'Y'
when accounts in ('final') then 'final'
else 'balance'
end as account_2
,
sum
(
(case when accounts in ('abc','def','ghi','final','x','y') then amount
else
(
(case when accounts in ('final') then (amount))-
(case when accounts in ('abc','def','ghi','x','y') then -amount else 0))
)
from new
Note: That balance of 5 represents thousands of small accounts which currently do not form part of a database.

If I understand correctly:
select Year, Month, Type, Accounts, Amount
from new
union all
select year, month, type, 'balance',
(sum(case when accounts = 'final' then amount else 0 end) -
sum(case when accounts <> 'final' then amount else 0 end)
)
from new
group by year, month, type;
Here is a db<>fiddle.

Related

How to get data from date

Hi I would like to get data from date for users. I ve got a table with all months but i would like to get how much they earn on month
user
month
money
1
january
10
2
january
1
1
april
100
2
april
1000
1
march
0
2
march
1
And result should be:
user
money_on_april
money_on_march
1
100
0
2
1000
1
3
0
0
Assuming you want a column for every month, or a certain subset of months:
SELECT
user,
SUM(CASE month WHEN 'january' THEN money ELSE 0 END) As money_on_january,
SUM(CASE month WHEN 'february' THEN money ELSE 0 END) As money_on_february,
...
FROM
YourTable
GROUP BY
user
If you only want columns for the months which exist in the table, then you'll need to use dynamic SQL instead.
If you are using MS SQL, Try PIVOT
SELECT * FROM [Your Table]
PIVOT(
SUM([money])
FOR [month] IN ([january],[april],[march])
)pvt

How to subtract result of 2 queries grouped by a field

I have a table in this form:
id year type amount
1 2015 in 10
2 2015 out 5
3 2016 in 20
4 2016 out 1
...
The followin query will give me the sum of the amount of type = 'in' grouped by year:
SELECT year, sum(amount)
FROM table
WHERE type = in
GROUP BY year
How am I going to get the following result?
year sum(in) sum(out) "in-out"
2015 10 5 5
2016 20 1 19
sum(in) is the sum of the 'amount' where type='in'.
Use a CASE statement to handle the values of type.
SELECT year,
SUM(CASE WHEN type = 'in' THEN amount ELSE 0 END) AS sum_in,
SUM(CASE WHEN type = 'out' THEN amount ELSE 0 END) AS sum_out,
SUM(CASE WHEN type = 'in' THEN amount ELSE -amount END) AS in_out
FROM table
GROUP BY year;

Return zero value for all the month in series with count zero

This is my query:
SELECT STAFF.stf_first_name + '' + STAFF.stf_last_name As Name,
DATENAME(month,RES_HAB_DATA.reshabdata_data_date) As Month,
SUM(case when RES_HAB_DATA.reshabdata_duration > 0
then (RES_HAB_DATA.reshabdata_duration/15) else 0 end) As ServiceDeliveryTime,
MONTH(RES_HAB_DATA.reshabdata_data_date) As MonthNumber
FROM RES_HAB_DATA
JOIN RES_HAB ON RES_HAB_DATA.reshab_id = RES_HAB.reshab_id
JOIN STAFF ON RES_HAB_DATA.staff_id = STAFF.stf_id
WHERE RES_HAB.serv_id = 30
AND RES_HAB_DATA.reshabdata_data_date >= '1/1/2015'
GROUP BY STAFF.stf_last_name,
STAFF.stf_first_name,
DATENAME(month,RES_HAB_DATA.reshabdata_data_date),
MONTH(RES_HAB_DATA.reshabdata_data_date)
ORDER BY MonthNumber
Which produces result set as:
Name Month ServiceDeliveryTime MonthNumber
----------------------------------------------------------------------------
mb January 52 1
MikeCasey January 10 1
MikeCasey February 4 2
PrecisionCareSupport February 0 2
MikeCasey March 4 3
PrecisionCareSupport March 0 3
MikeCasey April 8 4
PrecisionCareSupport April 0 4
MikeCasey May 16 5
MikeCasey July 4 7
PrecisionCareSupport July 1 7
PrecisionCareSupport August 0 8
MikeCasey September 10 9
MikeCasey October 12 10
I am generating a chart and would like to generate series for that chart but the series should be formed in a way that each series label must have all the tick values(zero if missing respective month). In Simple words,I want resultset as:
Name Month ServiceDeliveryTime MonthNumber
----------------------------------------------------------------------------
mb January 52 1
mb February 0 2
mb March 0 3
mb April 0 4
- - 0 5
Upto December then series will continue for Client MikeCasey upto December and so on...for all the series Labels.If any of the tick is missing for that client there will be value zero for that month.
How Can I produce this result set ? I want some uniform solution because there can be number of such queries for different charts.
Mr Shaw, try this
;WITH
(SELECT STAFF.stf_first_name + '' + STAFF.stf_last_name As Name,
DATENAME(month,RES_HAB_DATA.reshabdata_data_date) As Month,
SUM(case when RES_HAB_DATA.reshabdata_duration > 0
then (RES_HAB_DATA.reshabdata_duration/15) else 0 end) As ServiceDeliveryTime,
MONTH(RES_HAB_DATA.reshabdata_data_date) As MonthNumber
FROM RES_HAB_DATA
JOIN RES_HAB ON RES_HAB_DATA.reshab_id = RES_HAB.reshab_id
JOIN STAFF ON RES_HAB_DATA.staff_id = STAFF.stf_id
WHERE RES_HAB.serv_id = 30
AND RES_HAB_DATA.reshabdata_data_date >= '1/1/2015'
GROUP BY STAFF.stf_last_name,
STAFF.stf_first_name,
DATENAME(month,RES_HAB_DATA.reshabdata_data_date),
MONTH(RES_HAB_DATA.reshabdata_data_date)
) AS mytable
SELECT
myTableName.Name
,mytableMonth.Month
,ISNULL(mytable.ServiceDeliveryTime,0)
,mutableMonth.MonthNumber
FROM
(SELECT DISTINCT Name from mytable) mytableName
CROSS JOIN (SELECT DISTINCT Month,MonthNumber FROM mytable) mytableMonth
LEFT INNER JOIN mytable ON mytableName.Name = mytable.Name AND mytableMonth.Month = mytable.Month AND mytableMonthNumber = mytable.MonthNumber
ORDER BY mytableName.Name, mytableMonth.MonthNumber
I have taken all distinct months and names from your data and done a cross join.
;WITH mytable(Name,Month,ServiceDeliveryTime,MonthNumber) AS
(
SELECT STAFF.stf_first_name + '' + STAFF.stf_last_name As Name,
DATENAME(month,RES_HAB_DATA.reshabdata_data_date) As Month,
SUM(case when RES_HAB_DATA.reshabdata_duration > 0
then (RES_HAB_DATA.reshabdata_duration/15) else 0 end) As ServiceDeliveryTime,
MONTH(RES_HAB_DATA.reshabdata_data_date) As MonthNumber
FROM RES_HAB_DATA
JOIN RES_HAB ON RES_HAB_DATA.reshab_id = RES_HAB.reshab_id
JOIN STAFF ON RES_HAB_DATA.staff_id = STAFF.stf_id
WHERE RES_HAB.serv_id = 30
AND RES_HAB_DATA.reshabdata_data_date >= '1/1/2015'
GROUP BY STAFF.stf_last_name,
STAFF.stf_first_name,
DATENAME(month,RES_HAB_DATA.reshabdata_data_date),
MONTH(RES_HAB_DATA.reshabdata_data_date)
)
SELECT
myTableName.Name
,mytableMonth.Month_Name
,ISNULL(mytable.ServiceDeliveryTime,0) as ServiceDeliveryTime
,mytableMonth.id
FROM
(SELECT DISTINCT Name from mytable) mytableName
CROSS JOIN (SELECT DISTINCT Month_Name,id FROM MyMonths) mytableMonth
LEFT JOIN mytable ON mytableName.Name = mytable.Name AND mytableMonth.Month_Name = mytable.Month AND mytable.MonthNumber = mytable.MonthNumber
ORDER BY mytableName.Name, mytableMonth.id
MyMonths table is already created table with id as MonthNumber and Month_Name as Month.
Cheers!

Select Count usage divided by month

I do have a table license_Usage where which works like a log of the usage of licenses in a day
ID User license date
1 1 A 22/1/2015
2 1 A 23/1/2015
3 1 B 23/1/2015
4 1 A 24/1/2015
5 2 A 22/2/2015
6 2 A 23/2/2015
7 1 B 23/2/2015
Where I want to Count how many licenses a user used in a month, the result should look like:
User Jan Feb
1 2 1 ...
2 0 2
How can I manage to do that???
You need a PIVOT or cross tab query. e.g.
SELECT [User],
COUNT(CASE WHEN Month = 1 THEN 1 END) AS Jan,
COUNT(CASE WHEN Month = 2 THEN 1 END) AS Feb,
COUNT(CASE WHEN Month = 3 THEN 1 END) AS Mar
/*TODO - Fill in other 9 months using above pattern*/
FROM [license]
CROSS APPLY (SELECT MONTH([date])) AS CA(Month)
WHERE [date] >= '20150101'
AND [date] < '20160101'
AND [license] = 'A'
GROUP BY [User]
SQL Fiddle

Row as column in SQL Server 2008

I am working with SQL Server 2008. I have a temp table which returns the this result
Location Month value
US January 10
US February 10
US March 10
US April 10
US May 10
US June 10
UK January 10
UK January 10
UK February 10
UK February 10
UK March 10
UK March 10
UK April 10
UK April 10
UK May 10
UK May 10
UK June 10
UK June 10
I want to get the result as below
Location January February March Q1 April May June Q2
US 10 10 10 30 10 10 10 30
UK 20 20 20 60 20 20 20 60
How to query to get the above result using SQL Server 2008?
You can use this query, you have to complete it to fit your needs with all missing months/quarters:
select Location
,sum(case when [Month] = 'January' then value else 0 end) as January
,sum(case when [Month] = 'February' then value else 0 end) as February
,sum(case when [Month] = 'March' then value else 0 end) as March
,sum(case when [Month] in ( 'January', 'February', 'March')
then value else 0 end) as Q1
...
-- Repeat months...
...
,sum(value) as AllMonthTotal
from myTempTable
group by Location
-- UNION to get rowwise total
union
select 'TOTAL'
,sum(case when [Month] = 'January' then value else 0 end) as January
,sum(case when [Month] = 'February' then value else 0 end) as February
,sum(case when [Month] = 'March' then value else 0 end) as March
,sum(case when [Month] in ( 'January', 'February', 'March')
then value else 0 end) as Q1
...
-- Repeat months...
...
,sum(value) as AllMonthTotal
from myTempTable
There's also the PIVOT method:
Using PIVOT in SQL Server 2008
MSSQL dynamic pivot column values to column header