SSRS Expression - Subtract SUMS - sql

I need some help with an SSRS expression that sums up amounts and then subtracts sums. I have a dataset that has accounts and corresponding money/amount values. I'm trying to write an expression that sums up the money/amount values from one group of the accounts in a specified range, and then subtracts it from the money/amount total of another range. For example:
(Sum(amt) where acct between 40000 and 49999) -
(Sum(amt) where (acct between 50000 and 59999) or (acct between 66000 and 69999)) -
(Sum(amt) where acct between 76000 and 79825) -
(Sum(amt) where acct between 89000 and 90399)
I could really use some help translating the SQL logic above into an expression to be used for a textbox in SSRS. Any advice would be really helpful! Thanks!

Try this :-
=Sum(
iif(Fields!acct.Value) >= 1 and
Fields!acct.Value) < 4 ,
Fields!amt.Value,0
)
)
-
Sum(
iif(
(Fields!acct.Value>=5 and Fields!acct.Value<10)
or (Fields!acct.Value>=12 and Fields!acct.Value< 15),
Fields!amt.Value,0
)
)
-
Sum(
iif(
Fields!acct.Value) >= 76000 and
Fields!acct.Value) < 79825 ,
Fields!amt.Value,0
)
)
-
Sum(
iif(
Fields!acct.Value) >= 89000 and
Fields!acct.Value) < 90399 ,
Fields!amt.Value,0
)
)

Related

SQL sum with limit

i need to sum working hours from employees with some limitations. My code right now just for one employee:
SELECT rp.mnr,
trunc(sum(rp.OUT_DATE-rp.IN_DATE)*24, 2) AS "Hours"
FROM table1 rp
WHERE rp.CALC_DATE >= '01.04.2022' and rp.CALC_DATE <= '30.4.2022'
AND rp.MNR = 90590
GROUP BY rp.MNR
ORDER BY rp.mnr desc
MNR |Hours |
-----+------+
90590|181.98|
I need to split this sum with hours limit 50.. Result should look like:
MNR |Hours |
-----+------+
90590|50.00|
90590|50.00|
90590|50.00|
90590|31.98|
Anyone can help me with that ?
DB: Oracle.
Thank you!
MF
You have to generate the required rows to get your desired output. CONNECT BY clause is one of the method -
WITH DATA AS (<YOUR SELECT QUERY GIVING COLUMNS AS MNR AND HOURS>),
FIXED_AMOUNT AS (SELECT 50 AMT FROM DUAL),
CALC AS (SELECT D.*, AMT, SUM(AMT) OVER (ORDER BY ROWNUM) CUMM_SUM
FROM DATA D, FIXED_AMOUNT
CONNECT BY (LEVEL - 1) * 50 <= HOURS)
SELECT MNR, CASE WHEN HOURS_ - CUMM_SUM < 0
THEN HOURS_ - CUMM_SUM + AMT
ELSE AMT
END HOURS
FROM CALC;
Demo.

DAX Measure - Summing up values between start-end dates in the same table

I have an "Assignments" Table like this:
Date End Date Allocation1111 Alex AA 11/20/2016 12/30/2016 0.52222 Eric BB 10/20/2016 11/30/2016 0.43333 John CC 10/20/2016 12/30/2016 12222 Eric DD 11/20/2016 1/1/2017 0.5
I also have a simple "Date" Table which DOES NOT have a relationship with the Assignments Table like this:
Date Month Month_Text Year Month-Year10/1/2016 10 Oct 2016 Oct-1610/2/2016 10 Oct 2016 Oct-1610/3/2016 10 Oct 2016 Oct-1610/4/2016 10 Oct 2016 Oct-16
Than I have the following DAX measure:
==============================
Sum of Assignments :=CALCULATE ( SUMX ( Assignments_Tbl, Assignments_Tbl[Allocation] ), FILTER ( VALUES ( Date_Tbl ), Date_Tbl[Date] >= MINX ( Assignments_Tbl, Assignments_Tbl[Start Date] ) && Date_Tbl[Date] <= MAXX ( Assignments_Tbl, Assignments_Tbl[End Date] ) )) * CALCULATE ( DISTINCTCOUNT ( Date_Tbl[Month] ), FILTER ( VALUES ( Date_Tbl ), Date_Tbl[Date] >= MINX ( Assignments_Tbl, Assignments_Tbl[Start Date] ) && Date_Tbl[Date] <= MAXX ( Assignments_Tbl, Assignments_Tbl[End Date] ) ) )
==============================
All seems OK when I have the Start Date and End Date as part of my Pivot Table like below:
Sum of Assignments in a pivot table with Start/End Dates
HOWEVER, if I remove the Start Date and End Date from the pivot table, the measure is calculating incorrectly and I can't find why.
For instance, as the pic below, the red circles show 0.9 for a person name "Eric" in in Oct-2016, instead of 0.4.
Sum of Assignments measure calculating incorrectly
I tried many things, but got stuck on this measure. Any idea?
After some deeper investigation, here is the proper measure:
New Measure =
SUMX (
Assignments_Tbl,
CALCULATE (
SUM ( Assignments_Tbl[Allocation] ) * DISTINCTCOUNT ( Date_Tbl[Month-Year] ),
FILTER (
VALUES ( Date_Tbl ),
Date_Tbl[Date] >= EARLIER ( Assignments_Tbl[Start Date], 1 )
&& Date_Tbl[Date] <= EARLIER ( Assignments_Tbl[End Date], 1 )
)
)
)

Mdx Median query

Could really use a hand from someone on this mdx query. I am trying to produce a rolling median for the last 365 days on per user and per day basis. I need the median to be the median per user response days. It seems like a simple computation but I cannot see how to get it to work with the crossjoin in the mix. Any help would be so very appreciated! If you even have a suggestion on a direction to attack this from that would be great.
SET [2Years] AS
'{[FirstOrderDate].[Full Date].&[2010-01-15T00:00:00]:[FirstOrderDate].[Full Date].[2012-08-20T00:00:00]}'
MEMBER [Measures].[2YearMedianLag]
AS
median({[FirstOrderDate].[Full Date].currentmember.lag(365):[FirstOrderDate].[FullDate].currentmember} , [Measures].[Response Days])
SELECT {[Measures].[Response Days], [Measures].[MedianLag]} ON 0,
NonEmpty(crossjoin( [days],
[User].[User ID].children),[Measures].[Response Days]) ON 1
FROM [UserRevenue]
Thank you in advance for your assistance. 
EDIT:
SampleData (UserName varchar(100) null, FirstOrderDate Datetime null, ResponseDays int null)
('Jim', '2001-01-03', 10)
('Fred', '2001-01-03', 80)
('Frank', '2001-01-04', 30)
('Sally', '2001-01-05', 18)
('Joan', '2001-01-06', 26)
('Bill', '2001-01-06', 15)
('Ted', '2001-01-08', 29)
('Sam', '2001-01-10', 9)
('Jane', '2001-01-17', 200)
SampleOutput (FirstOrderDate datetime null, MedianResponseDays int null)
('2001-01-03', 45)
('2001-01-04', 30)
('2001-01-05', 24)
('2001-01-06', 22)
('2001-01-07', 22)
('2001-01-08', 26)
('2001-01-09', 26)
('2001-01-10', 22)
('2001-01-11', 22)
('2001-01-12', 22)
('2001-01-13', 22)
('2001-01-14', 22)
('2001-01-15', 22)
('2001-01-16', 22)
('2001-01-17', 26)
It's tricky because you need to work with a different set of rolling dates per day on rows. Are you sure you want 365 for the lag? That gives you 1 year plus 1 day. Anyway, this technique uses an inline named set to create a named set for each combination of user/date and assigns it a unique number, then you can pull that named set back out again in a StrToSet function to match up with the current row's user and dates. This version factors in each individual user:
with
set Users as [User].[User ID].Children
set UsersDates as NonEmpty((Users, [FirstOrderDate].[Full Date].children), [Measures].[Response Days])
set [Rolling Period] as
Generate(
UsersDates,
StrToSet(
"{[FirstOrderDate].[Full Date].currentmember.lag(364): [FirstOrderDate].[Full Date].currentmember} as RP" + CStr(UsersDates.CurrentOrdinal)
)
)
member [Measures].[Median Lag] as
median(
StrToSet("RP" +
CStr(Rank(([User].[User ID].CurrentMember, [FirstOrderDate].[Full Date].CurrentMember), UsersDates)))
, [Measures].[Response Days])
select
{
[measures].[Response Days]
, [measures].[Median Lag]
}
on columns,
UsersDates
on rows
from UserRevenue
UPDATE #1: This version ignores the individual user and instead uses the response for all users for the applicable set of dates:
with
set Users as [User].[User ID].Children
set Dates as NonEmpty([FirstOrderDate].[Full Date].children, [Measures].[Response Days])
set [Rolling Period] as
Generate(
Dates,
StrToSet(
"{[FirstOrderDate].[Full Date].currentmember.lag(364): [FirstOrderDate].[Full Date].currentmember} as RP"
+ CStr(Dates.CurrentOrdinal)
)
)
member [Measures].[Median Lag] as
median(
StrToSet("RP" +
CStr(Rank([FirstOrderDate].[Full Date].CurrentMember, Dates)))
, ([Measures].[Response Days], [User].[User ID].[All]))
select
{
[measures].[Response Days]
, [measures].[Median Lag]
}
on columns,
(Users, Dates)
on rows
from UserRevenue
UPDATE #2: Third time's a charm? Here's a query that gets me the results in your sample output. The key is that the set needs to generate a tuple for each date/user combination for the current date and store that as an inline named set, one per possible date which is uniquely identified by rank. So the first date (1/3) is rank 1, second date (1/4) is rank 2 etc when you look at the list of dates on rows. The first date 1/3/2001 has two items in the set - one with Jim for 1/3 and one with Fred for 1/3. So in the median calculation, the response days for each item in the related set need to be used. Because 1/3 is rank 1 in the list dates, the set called RP1 is retrieved, combined with response days for the items in the set (Jim and Fred) and the median is calculated. Then the next date, 1/4, contains three items - the same as for 1/3 but now also Frank for 1/4, so that requires a recalculation of the median and so on.
with
set Users as [User].[User ID].Children
set Dates as [FirstOrderDate].[Full Date].children
set [Rolling Period] as
Generate(
Dates,
StrToSet(
"NonEmpty(({[FirstOrderDate].[Full Date].currentmember.lag(364): [FirstOrderDate].[Full Date].currentmember}
, Users), [Measures].[Response Days]) as RP"
+ CStr(Dates.CurrentOrdinal)
)
)
member [Measures].[Median Lag] as
median(
StrToSet("RP" +
CStr(Rank([FirstOrderDate].[Full Date].CurrentMember, Dates)))
, [Measures].[Response Days])
select
{[measures].[Median Lag]}
on columns,
Dates
on rows
from UserRevenue
The MedianResponseDays measure iterates on the user to compute the median value of Response Days from a given date to the current date. I put the 365 days. on the rows.
WITH MEMBER [Measures].[MedianResponseDays] AS
Median([User].[User ID].children * [FirstOrderDate].[FullDate].CurrentMember:[FirstOrderDate].[FullDate].DefaultMember, [Measures].[Response Days])
SELECT {[Measures].[MedianResponseDays]} ON 0,
NON EMPTY {[FirstOrderDate].[Full Date].currentmember.lag(364):[FirstOrderDate].[FullDate].currentmember} ON 1
FROM [UserRevenue]
I have a fact table fct_line_details having two columns mtid, productivity
mtid productivity
---- ------------
1 400
1 200
1 600
2 700
3 900
I want to calculate the median for each mtid in SSAS . (median for mtid 1=400 )

MDX Count over time (years - not within a year)

I'd like to be able to rollup the count of commitments to a product over years -
The data for new commitments in each year looks like this:
Year | Count of new commitments | (What I'd like - count of new commitments to date)
1986 4 4
1987 22 26
1988 14 40
1989 1 41
I know that within a year you can do year to date, month to date etc, but I need to do it over multiple years.
the mdx that gives me the first 2 columns is (really simple - but I don't know where to go from here):
select [Measures].[Commitment Count] on 0
, [Date Dim].[CY Hierarchy].[Calendar Year] on 1
from [Cube]
Any help would be great
In MDX something along the line:
with member [x] as sum(
[Date Dim].[CY Hierarchy].[Calendar Year].members(0) : [Date Dim].[CY Hierarchy].currentMember,
[Measures].[Commitment Count]
)
select [x] on 0, [Date Dim].[CY Hierarchy].[Calendar Year] on 1 from [Cube]
Use a common table expression:
with sums (year,sumThisYear,cumulativeSum)
as (
select year
, sum(commitments) as sumThisYear
, sum(commitments) as cumulativeSum
from theTable
where year = (select min(year) from theTable)
group by year
union all
select child.year
, sum(child.commitments) as sumThisYear
, sum(child.commitments) + parent.cumulativeSum as cumulativeSum
from sums par
JOIN thetable Child on par.year = child.year - 1
group by child.year,parent.cumulativeSum
)
select * from sums
There's a bit of a "trick" in there grouping on parent.cumulativeSum. We know that this will be the same value for all rows, and we need to add it to sum(child.commitments), so we group on it so SQL Server will let us refer to it. That can probably be cleaned up to remove what might be called a "smell", but it will work.
Warning: 11:15pm where I am, written off the top of my head, may need a tweak or two.
EDIT: forgot the group by in the anchor clause, added that in

How can I calculate a column data for different conditions using single query in sql server?

I am using below query to count a particular column data based on single condition.
SELECT COUNT(DISTINCT(S.INVOICENO)) AS LESSTWO , YEAR(S.invoicedate) YER,
Month(S.invoicedate) MNTH
FROM SALESDATA S
where S.BILLINGTYPE='INVOICE'
AND (S.invoicedate >='4-1-2009' and S.invoicedate <='4-30-2010')
AND S.TAXABLEAMT <=2000
GROUP BY YEAR(S.invoicedate) ,Month(S.invoicedate)
ORDER BY YEAR(S.invoicedate) ,Month(S.invoicedate)
But I have to calculate for 3 more conditions. Is it possible to count based on 3 conditions(i.e. 2001 - 3000,3001 - 4000, 4001 - 5000,>5000) and I want result set for all the conditions?
Regards,
N.SRIRAM
Untested, but should be about right:
SELECT CASE
WHEN S.TaxableAmt <= 2000 THEN '<=2000'
WHEN S.TaxableAmt <= 3000 THEN '2001-3000'
WHEN S.TaxableAmt <= 4000 THEN '3001-4000'
ELSE '>5000'
END as Bracket,
COUNT(DISTINCT(S.INVOICENO)) AS LESSTWO , YEAR(S.invoicedate) YER,
Month(S.invoicedate) MNTH
FROM SALESDATA S
where S.BILLINGTYPE='INVOICE'
AND (S.invoicedate >='20090401' and S.invoicedate <='20100430')
GROUP BY
CASE
WHEN S.TaxableAmt <= 2000 THEN '<=2000'
WHEN S.TaxableAmt <= 3000 THEN '2001-3000'
WHEN S.TaxableAmt <= 4000 THEN '3001-4000'
ELSE '>5000'
END,
YEAR(S.invoicedate) ,Month(S.invoicedate)
ORDER BY YEAR(S.invoicedate) ,Month(S.invoicedate)
You have to repeat the case expression in the GROUP BY clause (or put it all in a subquery), and I've fixed your date constants so that they're unambiguous.
I think you really need to split up the query into 3 distinct queries - one for each of the conditions you require