简体   繁体   中英

MDX - How to count a dimension based on an existence of sequencial days at fact table?

I need to get the quantity of students that match two criterias:

  1. have 3 sequencial absents at last 3 schoolar days, OR
  2. have 5 no sequencial absents at last 2 months.

I have the fact of Student's Absents by day with the follow fields:

  • StudentId
  • SchoolCalendarId
  • SchoolId
  • ClassId
  • QtyAbsents (always 1, just to sum)

The dimensions:

  • DimStudent
  • DimSchoolCalendar
  • DimSchool
  • DimClass

I did a MDX that return the name of Students that match the first criteria:

WITH
    MEMBER [A] AS 
        CASE
            WHEN [Measures].[QtyLackingStudents] = 3 
            THEN 'THREE SEQUENCIAL ABSENTS' ELSE NULL END
SELECT
    NON EMPTY { [A] } ON COLUMNS,
    NON EMPTY { [DimStudent].[Name].ALLMEMBERS } ON ROWS
FROM
(
    SELECT
        ( FILTER(
            [DimSchoolCalendar].[Date].MEMBERS,
            [DimSchoolCalendar].[Date].CURRENTMEMBER.NAME = VBAMDX!Format(VBAMDX!Now(),"yyyy-MM-dd")
        ).ITEM(0).Lag(3):FILTER(
            [DimSchoolCalendar].[Date].MEMBERS,
            [DimSchoolCalendar].[Date].CURRENTMEMBER.NAME = VBAMDX!Format(VBAMDX!Now(),"yyyy-MM-dd")
        ).ITEM(0) ) ON COLUMNS
    FROM 
        (
            SELECT 
                ( { [DimSchoolCalendar].[SchoolDay].&[IsSchoolDay] } ) ON COLUMNS
            FROM [AlunosMatriculados]
        )
)

But I could neither do the second criteria nor put everything in a single measure.

EDIT:

I made a SQL that returns what I want. I need the MDX.

SELECT COUNT(DISTINCT f.StudentId)
FROM DW.FactLackingStudents f
    INNER JOIN DW.DimSchool e ON e.SchoolId = f.SchoolId
    INNER JOIN DW.DimSchoolCalendar ce ON ce.SchoolCalendarId = f.SchoolCalendarId
WHERE (SELECT COUNT(*) 
        FROM DM.FactLackingStudents f2
            INNER JOIN (
                SELECT c.SchoolCalendarId
                    , ROW_NUMBER() OVER(PARTITION BY c.Year, c.SchoolId ORDER BY c.Date DESC) AS Seq
                FROM dm.DimCalendarioEscolar c
                WHERE c.Year = a.Year
                    and c.SchoolKey = e.SchoolKey
                    and c.Date < GETDATE()
                    and c.SchoolDay = 'IS SCHOOL DAY'
            ) days ON days.SchoolCalendarId = f2.SchoolCalendarId
                and days.Seq <= 3
        WHERE f2.StudentId = f.StudentId) = 3   -- ABSENTS AT LAST 3 SCHOOL DAYS IS EQUAL 3
    OR 
    (
        SELECT COUNT(*) 
        FROM DM.FactLackingStudents f2
            INNER JOIN (
                SELECT c.SchoolCalendarId
                    , ROW_NUMBER() OVER(PARTITION BY c.Year, c.SchoolId ORDER BY c.Date DESC) AS Seq
                FROM dm.DimCalendarioEscolar c
                WHERE c.Year = a.Year
                    and c.SchoolKey = e.SchoolKey
                    and c.Date BETWEEN DATEADD(DD, -60, GETDATE()) AND GETDATE() -- LAST 2 MONTHS
                    and c.SchoolDay = 'IS SCHOOL DAY'
            ) days ON days.SKCalendarioEscolar = f2.SKDataInfrequencia
        WHERE f2.StudentId = f.StudentId
    ) >= 5  -- ABSENTS AT LAST 60 DAYS IS EQUAL 5

Step by step:

The first criteria

Create a day set where all days from the very beginning to today:

{NULL:StrToMember('[DimSchoolCalendar].[Date].&[' + Format(Now(),'yyyy-MM-dd') + ']')}

Cross join the set with IsSchoolDay in order to get school days only:

[DimSchoolCalendar].[SchoolDay].&[IsSchoolDay] * {NULL:StrToMember('[DimSchoolCalendar].[Date].&[' + Format(Now(),'yyyy-MM-dd') + ']')}

Obtain the last three members from the set:

Tail(               
    [DimSchoolCalendar].[SchoolDay].&[IsSchoolDay] * {NULL:StrToMember('[DimSchoolCalendar].[Date].&[' + Format(Now(),'yyyy-MM-dd') + ']')},
    3
)

Create a calculated measure:

SUM(    
    Tail(           
        [DimSchoolCalendar].[SchoolDay].&[IsSchoolDay] * {NULL:StrToMember('[DimSchoolCalendar].[Date].&[' + Format(Now(),'yyyy-MM-dd') + ']')},
        3
    ),
    [Measures].[QtyLackingStudents]
)

The second criteria

Get the current month:

StrToMember('[DimSchoolCalendar].[Month].&[' + Format(Now(),'yyyy-MM') + ']')

Get the last two month:

LastPeriods(
    2,
    StrToMember('[DimSchoolCalendar].[Month].&[' + Format(Now(),'yyyy-MM') + ']')
)

Create a calculated measure:

SUM(    
    LastPeriods(
        2,
        StrToMember('[DimSchoolCalendar].[Month].&[' + Format(Now(),'yyyy-MM') + ']')
    ),
    [Measures].[QtyLackingStudents]
)

The final result

With 
Member [Measures].[1 absent criteria] as
SUM(    
    Tail(

        [DimSchoolCalendar].[SchoolDay].&[IsSchoolDay] * {NULL:StrToMember('[DimSchoolCalendar].[Date].&[' + Format(Now(),'yyyy-MM-dd') + ']')},
        3
    ),
    [Measures].[QtyLackingStudents]
)

Member [Measures].[2 absent criteria] as
SUM(    
    LastPeriods(
        2,
        StrToMember('[DimSchoolCalendar].[Month].&[' + Format(Now(),'yyyy-MM') + ']')
    ),
    [Measures].[QtyLackingStudents]
)


Member [Measures].[Absents] as
case 
    when [Measures].[1 absent criteria] = 3 and [Measures].[2 absent criteria] >= 5
    then 'THREE SEQUENCIAL ABSENTS + FIVE ABSENTS LAST 2 MONTHS'
    when [Measures].[1 absent criteria] = 3
    then 'THREE SEQUENCIAL ABSENTS'
    when [Measures].[2 absent criteria] >= 5
    then 'FIVE ABSENTS LAST 2 MONTHS'
    else NULL
end 

Select 
{[Measures].[Absents]} on 0,
Non Empty {[DimStudent].[Name].[Name].Members} on 1
From [AlunosMatriculados]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM