Keyster2305
Keyster2305

Reputation: 21

Evaluate eligibility of clients based on active period

My query seems simple and maybe im over thinking it. Consider 2 tables: Client A and Service B. The clients table has 2 dates, Service Start Date & Service End Date. Now, our KPI is we should have provided atleast 1 service to each client that has been active with us for more than 15 days in that month. This is a monthly KPI. My interface lets you pick a 3 month or 6 month period for reporting and the report needed is Count of Client serviced by Month. This will be grouped by month and the Region they are in.

Client Table A

   C_ID |  Name | SrvStDt  | SrvEndDt  |  ServManager  | Region
    1   | ABCD  | 1 Jan 16 | 10 Mar 16 |    AAAAAA     |  North
    2   | EDFG  | 1 Feb 16 | 15 Aug 16 |    BBBBBB     |  South
    3   | YTHG  | 1 Mar 16 |  1 Jul 16 |    CCCCCC     |  East
    4   | WEFG  | 21 Apr 16| 15 May 16 |    DDDDDD     |  West
    5   | POIU  | 18 May 16| 15 Jul 16 |    AAAAAA     |  North
    6   | QWER  | 30 Jun 16|   --      |    BBBBBB     |  South
    7   | CVBH  | 21 Jul 16|   --      |    CCCCCC     |  East
    8   | ASDR  | 1 Aug 16 |   --      |    DDDDDD     |  West
    9   | LKJU  | 15 Jan 16| 15 Jul 16 |    AAAAAA     |  North
   10   | MNBU  | 15 Mar 16| 15 Jul 16 |    BBBBBB     |  South

Notes : No end date signifies the client is still active

Service Table B

   ID  |  SrvDAte
    1  | 15 Jan 16
    1  | 12 Feb 16
    1  | 01 Mar 16
    1  | 10 Mar 16
    2  | 15 Feb 16
    2  | 15 Mar 16
    2  | 31 Mar 16
    2  | 15 Apr 16
    2  | 15 May 16
    2  | 15 Jul 16
    2  | 15 Aug 16
    3  | 21 Mar 16
    3  | 23 Mar 16
    3  | 23 Apr 16
    3  | 23 May 16
    4  | 29 Apr 16
    5  | 23 May 16
    6  | 12 Jul 16
    7  | 23 Jul 16
    9  | 23 Mar 16
    9  | 23 Apr 16
    9  | 23 May 16
    10 | 19 Mar 16
    10 | 19 Apr 16
    10 | 19 May 16
    10 | 19 Jun 16

For a report from 1 April - 31 Jul the Result im after will look something like this:

    Region  |  Month | Total Active | Total Serviced
    North   | Apr-16 |  XXXX        |  XXXX
    North   | May-16 |  XXXX        |  XXXX
    North   | Jun-16 |  XXXX        |  XXXX
    North   | Jul-16 |  XXXX        |  XXXX
    South   | Apr-16 |  XXXX        |  XXXX
    South   | May-16 |  XXXX        |  XXXX
    South   | Jun-16 |  XXXX        |  XXXX
    South   | Jul-16 |  XXXX        |  XXXX
    East    | Apr-16 |  XXXX        |  XXXX
    East    | May-16 |  XXXX        |  XXXX
    East    | Jun-16 |  XXXX        |  XXXX
    East    | Jul-16 |  XXXX        |  XXXX
    West    | Apr-16 |  XXXX        |  XXXX
    West    | May-16 |  XXXX        |  XXXX
    West    | Jun-16 |  XXXX        |  XXXX
    West    | Jul-16 |  XXXX        |  XXXX

I'm struggling with how to identify clients that are active for at least 15 days in a month for all of the reporting period. I can put a between clause for the whole period, e.g., 1 Apr - 1 Jul, but how do I break it into months and evaluate for each month?

I'm using MS Access VBA & SQL queries. I would like an SQL query that gives me this result set.

Upvotes: 0

Views: 46

Answers (1)

Gord Thompson
Gord Thompson

Reputation: 123409

I'm struggling with how to identify clients that are active for at least 15 days in a month for all of the reporting period. I can put a between clause for the whole period, e.g., 1 Apr - 1 Jul, but how do I break it into months and evaluate for each month?

One way to derive those counts would be to use a "numbers table" that starts at zero and covers the largest possible number of days between the start date and the end date, e.g.,

[Numbers]

  n
---
  0
  1
  2
  3
...
998
999

Then, for sample data

[TableA]

C_ID  SrvStDt     SrvEndDt  
----  ----------  ----------
   1  2016-01-01  2016-01-04
   2  2016-02-28  2016-03-02
   3  2016-08-10            

the query

SELECT 
    C_ID, 
    DateAdd("d", n, SrvStDt) AS SrvDate
FROM TableA, Numbers
WHERE 
    DateAdd("d", n, SrvStDt) <= Nz(SrvEndDt, Date())

returns

C_ID  SrvDate   
----  ----------
   1  2016-01-01
   1  2016-01-02
   1  2016-01-03
   1  2016-01-04
   2  2016-02-28
   2  2016-02-29
   2  2016-03-01
   2  2016-03-02
   3  2016-08-10
   3  2016-08-11
   3  2016-08-12
   3  2016-08-13
   3  2016-08-14
   3  2016-08-15

and if we wrap that in an aggregation query to COUNT the dates in each Year/Month (GROUP BY)

SELECT
    C_ID,
    Year(SrvDate) AS SrvYear,
    Month(SrvDate) AS SrvMonth,
    COUNT(*) AS SrvDays
FROM
    (
        SELECT 
            C_ID, 
            DateAdd("d", n, SrvStDt) AS SrvDate
        FROM TableA, Numbers
        WHERE 
            DateAdd("d", n, SrvStDt) <= Nz(SrvEndDt, Date())
    )
GROUP BY
    C_ID,
    Year(SrvDate),
    Month(SrvDate)

we get

C_ID  SrvYear  SrvMonth  SrvDays
----  -------  --------  -------
   1     2016         1        4
   2     2016         2        2
   2     2016         3        2
   3     2016         8        6

Upvotes: 1

Related Questions