YTD budget table to current period in SQL - sql

I have a table in the following format (pseudo code):
CREATE TABLE [GLM_MASTER__BUDGET](
[Budget_Year],
[Budget_Type],
[Account],
[Period_1_Budget],
[Period_2_Budget],
[Period_3_Budget],
[Period_4_Budget],
[Period_5_Budget],
[Period_6_Budget],
[Period_7_Budget],
[Period_8_Budget],
[Period_9_Budget],
[Period_10_Budget],
[Period_11_Budget],
[Period_12_Budget]
)
I need to be able to query this with a with of a int for the current period like 6
This should return the the combined values of all periods from 1 to the number specified.
So I would end up with an output like this:
Budget_Year, Budget Type, Account, (Sum of all periods from 1 to the period specified) as Amount
I am using MS SQL server so it would be ok at the top to do something like:
DECLARE #current_period INT = 6

If you have the opportunity to redesign this table you may wish to consider it now.
You could use something along these lines:
DECLARE #current_period INT = 6
SELECT
Budget_Year, Budget Type, Account,
CASE WHEN #current_period >= 1 THEN [Period_1_Budget] ELSE 0 END +
CASE WHEN #current_period >= 2 THEN [Period_2_Budget] ELSE 0 END +
CASE WHEN #current_period >= 3 THEN [Period_3_Budget] ELSE 0 END +
CASE WHEN #current_period >= 4 THEN [Period_4_Budget] ELSE 0 END +
.....
..
CASE WHEN #current_period >= 12 THEN [Period_12_Budget] ELSE 0 END As Amount
FROM [GLM_MASTER__BUDGET]
Also it's not clear from your description whether you require a SUM and GROUP BY so I've left it out.

Related

Find the next date based on Interval (month/quaterly)

CREATE TABLE #Temp(
Date datetime,
Flag bit)
#Temp table as data from 01-04-2019 to 31-04-2020 (366 records) and flag=0
DECLARE startdate date='12-04-2019', interval int =1 OR 3
Expected Result: If interval is 1 month, based on startdate, flag to be updated as 1 below records and rest for 0
date flag
01-04-2019 0
. 0
. 0
12-05-2019 1
. 0
. 0
12-06-2019 1
. 0
. 0
12-07-2019 1
.. 0
31-04-2020 0
If interval is 3 month, flag to be updated as 1 for quarter
date flag
01-04-2019 0
. 0
. 0
12-07-2019 1
. 0
. 0
12-10-2019 1
. 0
. 0
12-01-2020 1
. 0
31-04-2020 0
I am stuck trying get the result. I am using SQL Server 2017.
Took me awhile to realize that your dates were in different format than I'm used to.
I would go with a common table expression as opposed to a cursor. Besides that, consider the month difference between any given date and the start date. Take the modulo of that difference (that's what the '%' symbol is). If it's 0, then your interval has been hit and so activate your flag.
declare
#startdate date = '04.01.2019',
#interval int = 3; -- or 1, or whatever
with
dates as (
select #startdate dt, 1 flag
union all
select ap.nextDt,
flag =
case
when day(ap.nextDt) <> day(#startdate) then 0
when (month(ap.nextDt) - month(#startdate)) % #interval = 0 then 1
else 0
end
from dates
cross apply (select nextDt = dateadd(day,1,dt)) ap
where dt <= dateadd(year,1,#startdate)
)
select *
from dates
option (maxrecursion 367)

BASIC SQL - Case expression - Modifying "Then 1 Else 0" To return count of rows where case statement is true

I am a sales professional interested in honing my SQL skills further. Stackoverflow has been a great resource for me thus far!
Goal:
I want to get a distinct count of all our customers by DMA (aka Metro U.S. Area) where the case expression below is true.
PROBLEM
Right now, when I execute the query, the resulting count for the "current month -1" column (which should return the count of all customers who match the case statement) is just returning a 1. I would like for this to return the count of o.intorgnodeID (customer IDS) in which the case expression was true (57 customers).
In other words, I suspect that the "then 1" part of the case statement is what is causing me issues. But I am not sure how to modify the "1' to count just the results of the original case statement
SELECT
o.strDMANode --- AKA Metro Market
,case when(sum(case when (year(getdate()) - 1) * 12 + month(getdate()) - ((year(sbi.dtmdelivered) - 1) * 12 + month(sbi.dtmdelivered)) = 24 then 1 else 0 end)) >0 then 1 else 0 end as 'Current Month - 1' --- this is the output column that I hope to have return a value of '57'. Currently is returning a '1'
FROM sqlfact.dbo.uvwreport as sbi
JOIN [sqlDim].[dbo].[uvwdimOrgNodeType1] o ON [sbi].[intDimOrgNodeID] = [o].[intDimOrgNodeID]
JOIN [sqlDim].[dbo].[uvwdimProductType1] as "z" ON [sbi].[intDimProductPrimaryID] = [z].[intDimProductID]
WHERE
([sbi].[intstatusid] = 5 OR sbi.intsubstatusid = 43) --- Includes only delivered reports
and [sbi].[mnyDollarcost] > 0 --- NO $0 reports
and [o].[bitCurrent] = 1 --- Excludes all historical versions of OrgNode, which were duplicates
and [o].[strSalesRegionNodeGroup] = 'Construction'
GROUP BY [o].[strDMANode]
ORDER BY [o].[strDMANode] asc
CURRENT RESULTS:
strDMANode Result
ABILENE-SWEETWATER DMA 1
DESIRED RESULTS:
strDMANode Column Result
ABILENE-SWEETWATER DMA 57
I think you want the case as an argument to sum():
sum(case when(case when (year(getdate()) - 1) * 12 + month(getdate()) - ((year(sbi.dtmdelivered) - 1) * 12 + month(sbi.dtmdelivered)) = 24 then 1 else 0 end)) >0 then 1 else 0 end) as 'Current Month - 1'

Using COUNT CASE WHEN MONTH Statement in MariaDB 10.2.15

I created a query to calculate the Amount of Id in a table using COUNT, CASE, WHEN and MONTH ..
Code:
SELECT
COUNT(CASE WHEN MONTH(LogsFormatted.DateIn) = 1 THEN LogsFormatted.Id ELSE 0 END ) AS '1',
COUNT(CASE WHEN MONTH(LogsFormatted.DateIn) = 2 THEN LogsFormatted.Id ELSE 0 END ) AS '2'
FROM
HrAttLogsFormatted AS LogsFormatted
WHERE
LogsFormatted.DateIn BETWEEN '2019-01-01' AND '2019-02-31'
AND LogsFormatted.Late != ''
Output :
| 1 | 2 |
| 1378 | 1378 |
The output I want to make is to calculate the Id in each month, namely Month 1 and Month 2
| 1 | 2 |
| 792 | 586 |
The data above is a fact
Using the above query instead adds up between the results of calculating month 1 and month 2
You should be counting NULL when the criteria in your CASE expression does not match. Also, I prefer counting 1 unless you really want to the count the Ids themselves. This version should work:
SELECT
COUNT(CASE WHEN MONTH(lf.DateIn) = 1 THEN 1 END) AS '1',
COUNT(CASE WHEN MONTH(lf.DateIn) = 2 THEN 1 END) AS '2'
FROM HrAttLogsFormatted AS lf
WHERE
lf.DateIn BETWEEN '2019-01-01' AND '2019-02-31' AND
lf.Late != '';
Note carefully that the current counts you are seeing sum up to the individual counts, that is:
1378 = 792 + 586
The reason for this is the the COUNT function "counts" any non NULL value as 1, and any NULL value as zero. Your current CASE expression will always count 1, for every record in the table.
remove else part from case when expression - if you use else with 0 then count takes that also in consideration which gives u actually wrong ouput
SELECT
COUNT(CASE WHEN MONTH(LogsFormatted.DateIn) = 1 THEN LogsFormatted.Id END ) AS '1',
COUNT(CASE WHEN MONTH(LogsFormatted.DateIn) = 2 THEN LogsFormatted.Id END ) AS '2'
FROM
HrAttLogsFormatted AS LogsFormatted
WHERE
LogsFormatted.DateIn BETWEEN '2019-01-01' AND '2019-02-31'
AND LogsFormatted.Late != ''
If you are using MariaDB, I would just use SUM() with a boolean:
SELECT SUM( MONTH(lf.DateIn) = 1 ) as month_1,
SUM( MONTH(lf.DateIn) = 2 ) as month_2
FROM HrAttLogsFormatted lf
WHERE lf.DateIn >= '2019-01-01' AND
lf.DateIn < '2020-01-01' AND
lf.Late <> '';
This assumes that the id that you are counting is never NULL (a reasonable assumption for an id).
Note other changes:
The column aliases do not need to be escaped. Don't use non-standard names, unless you need them -- for some reason -- for downstream processing.
This uses a shorter table alias, so the query is easier to write and to read.
The date comparisons use inequalities, so this works both for dates and datetimes.
<> is the standard SQL comparison operator for inequality.

SQL Query to sum buckets

I have a table with inovices and a field named Arrers days and I need to count how many items are into 0-30 days also 30-90 and 90-120
Basically what I need is to calcuate the aging of my client portfolio.
so far I have this:
SELECT SUM(CASE WHEN Receivable.Arrers>'0'<'30' THEN 1 ELSE 0) AS 0-30,
SUM(CASE WHEN Receivable.Arrers<'30'>'60' THEN 1 ELSE 0) AS 30-60,
SUM(CASE WHEN Receivable.Arrers<'90'>'120' THEN 1 ELSE 0) AS 90-120
From Receivable
Table Name Receivable
Invoice Arrers
89859 10
89856 3
89853 11
Access SQL does not support CASE WHEN. You can use an IIf expression instead.
SELECT
SUM(IIf(r.Arrers BETWEEN 0 AND 30, 1, 0)) AS [0-30],
SUM(IIf(r.Arrers BETWEEN 31 AND 60, 1, 0)) AS [31-60],
SUM(IIf(r.Arrers BETWEEN 90 AND 120, 1, 0)) AS [90-120]
FROM Receivable AS r;
The example in your question ignores Arrers from 61 to 89, so I did, too. But you can add in another column expression if needed.
If Arrers is text instead of numeric datatype, you can use Val() to cast the text values to numbers ...
SUM(IIf(Val(r.Arrers) BETWEEN 0 AND 30, 1, 0)) AS [0-30]
You can try that one
SELECT
SUM( CASE WHEN Receivable.Arrers BETWEEN 0 AND 30 THEN 1 ELSE 0) AS '0-30',
SUM (CASE WHEN Receivable.Arrers BETWEEN 30 AND 60 THEN 1 ELSE 0) AS '30-60',
SUM (CASE WHEN Receivable.Arrers BETWEEN 90 AND 120 THEN 1 ELSE 0) AS '90-120',
arrers
FROM Receivable
GROUP BY arrers
1 thing need to be checked.
I've put BETWEEN 90 AND 120 as I consider it integer. If they are varchar, you will need to turn them into integers. Val(Receivable.Arrers) will do the trick on access. Please let me know if there is anything unclear
You are on the right track except possibly for the CASE stmt syntax .... try Andy's answer without the Group by
(Dont have enough points to post as a comment)
I'd use something like this:
SELECT subq.ArrersGroup, COUNT(*) 'Count'
FROM
(
SELECT
CASE
WHEN R.Arrers < 30 THEN '0-30'
WHEN R.Arrers < 90 THEN '30-90'
WHEN R.Arrers < 120 THEN '90-120'
ELSE 'Other'
END ArrersGroup
FROM Receivable R
) subq
GROUP BY subq.ArrersGroup
SqlFiddle

SQL Server Sum table fields based on params

I have a table containing values from 12 different months
Table
{
January INT,
February INT,
etc.
}
and I need to sum values from specific months which numbers I keep in table (the number of months to sum can vary from 1 to 12):
DECLARE #Months TABLE
(
Number INT
)
so I'll surely need a big case and CTE but I don't really know how to achieve this.
The case statement isn't that bad:
select sum((case when m.month = 1 then Jan else 0 end) +
(case when m.month = 2 then Feb else 0 end) +
. . .
(case when m.month = 12 then Dec else 0 end)
)
from atable a cross join
#Months m;
You might want a group by as well. The above will return only one row for the entire table.