I often get requests from fellow staff members asking for a report about their “Regular” attendees.  After I explain to them that SQL doesn’t have a “Regular” key word, and that I need to know exactly what they mean by “regular” they usually  go away to think about it and never end up coming back :) .

Unfortunately they’ve begun to figure this out.  My latest report request was for a list of the parents of all 2nd –6th graders who have attended services at least twice a month for the previous 6 months, and if and where the parent might be serving.  Ok, that’s specific. Now how do I get the list?

Writing the SQL proved to be more challenging than I expected.  After a couple iterations, I finally just created a “utility” stored procedure that would accept a list of attendance types, a minimum monthly attendance rate, and the number of months to check the attendance.  It then returns a list of people who met that criteria.

Since it might come in handy for others, I share it here…

CREATE PROC [dbo].[cust_ccv_regular_attenders]
@OccurrenceTypeIDs varchar(200),
@MonthsBack int,
@MinMonthlyAttendance int

AS

/********************************************************************
*    cust_ccv_regular_attenders
*
*    Procedure to return list of people who have attended specific
*   occurrence type(s) a specific number of times each month for a
*    specific number of months back.
*
*    Parameters:
*        @OccurrenceTypeIDs - Comma delimeted list of occurrence type
*            ID's to check
*        @MonthsBack  - Number of months back that minimum attendance
*            has to have occurred
*        @MinMonthlyAttendance - The number of times each month that
*            person needs to have attended
*
*********************************************************************/

BEGIN

    DECLARE @Dates varchar(max)
    SET @Dates = ''
    DECLARE @Where varchar(max)
    SET @Where = ''

    DECLARE @Date datetime
    SET @Date = CAST(MONTH(GETDATE()) AS varchar) + '/1/' + CAST(YEAR(GETDATE()) AS varchar)
    SET @Date = DATEADD(month, -1, @Date)

    DECLARE @Month int
    SET @Month = -1

    WHILE @Date > DATEADD(month, (0 - (@MonthsBack + 1)), GETDATE())
    BEGIN

        IF @Dates <> ''
            SET @Dates = @Dates + ','
        SET @Dates = @Dates + '[' + CAST(MONTH(@Date) AS varchar) + '/1/' + CAST(YEAR(@Date) AS varchar) + ']'

        IF @Where = ''
            SET @Where = ' WHERE '
        ELSE
            SET @Where = @Where + ' AND '
        SET @Where = @Where + '[' + CAST(MONTH(@Date) AS varchar) + '/1/' + CAST(YEAR(@Date) AS varchar) + '] >= ' + CAST(@MinMonthlyAttendance AS varchar)

        SET @Date = DATEADD(month, -1, @Date)
    END

    DECLARE @Sql nvarchar(max)
    SET @Sql =
    'WITH CTE
    AS
    (
        SELECT *
        FROM (
            SELECT
                OA.person_id,
                CAST(MONTH(service_time) AS varchar) + ''/1/'' + CAST(YEAR(service_time) AS varchar) as service_month
            FROM core_occurrence_attendance OA
            INNER JOIN core_v_occurrence_service O ON O.occurrence_id = OA.occurrence_id
            WHERE O.occurrence_type_id in (' + @OccurrenceTypeIDs + ')
            AND OA.attended = 1
            AND OA.person_id IS NOT NULL
        )
        MS
        PIVOT (
            COUNT(service_month)
            FOR service_month
            IN (' + @Dates + ')
        ) AS pvt
    )
    SELECT person_id
    FROM CTE ' + @Where

    --SELECT @Sql
    EXEC sp_executesql @Sql;

END

Since that is now just a utility procedure, I needed another procedure to specify the elementary age occurrence types, join to the parents and find their serving areas…

CREATE PROC cust_ccv_sp_elementary_reg_attender_parents

AS

DECLARE @RegularAttenders table
(
    person_id int primary key not null
)

INSERT INTO @RegularAttenders
EXEC [cust_ccv_regular_attenders] '40,41,43,68,69', 6, 2

SELECT DISTINCT
    P.*,
    dbo.core_funct_profile_name_list(P.person_id, 2) AS Serving
FROM @RegularAttenders RA
INNER JOIN core_family_member C
    ON C.person_id = RA.person_id
    AND C.role_luid = 31
INNER JOIN core_family_member A
    ON A.family_id = C.family_id
    AND A.role_luid = 29
INNER JOIN core_v_merge_fields P
    ON P.person_id = A.person_id
ORDER BY P.last_name, P.nick_name

I created a new page in Arena that used the ReportGridFromQuery module, pointed it to this procedure, and now the elementary kids staff member can track down all the parents of their “regular” attendees who are not already serving and hit them up to serve in their area.

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>