sqlsql-serverdatabasecognos-10

Create a SQL query based Daily report with Incremental Records


I have a requirement to create a crosstab using a database which loads only incremental records. Please consider the following sample, Table1:

DAY         ACCOUNT NO  SALES   GENDER
1-Apr-2019  ACC01       5000    MALE
1-Apr-2019  ACC02       6000    FEMALE
1-Apr-2019  ACC03       7000    FEMALE
1-Apr-2019  ACC04       8000    MALE
2-Apr-2019  ACC01       7500    MALE
2-Apr-2019  ACC02       4000    FEMALE
2-Apr-2019  ACC03       10000   FEMALE
2-Apr-2019  ACC04       20000   MALE
3-Apr-2019  ACC01       8500    FEMALE
3-Apr-2019  ACC05       3500    FEMALE
4-Apr-2019  ACC02       9500    FEMALE
4-Apr-2019  ACC06       3600    FEMALE
4-Apr-2019  ACC07       4800    MALE
5-Apr-2019  ACC01       15000   FEMALE
5-Apr-2019  ACC03       12500   FEMALE

Table1 entries explained below:

1st April there are 4 accounts with their sale nos and gender of the account holder.
On 2nd April, there is some change in sale nos for all the accounts and thus they have been loaded.
But on 3rd April, we only load incremental accounts. As can be seen, the sales of ONLY ACC01 has changed and also there is a new account ACC05. Thus only these 2 accounts will be loaded.
Again on 4th April, existing account ACC02 has an increase in sale from its previous value and thus it gets loaded. Along with this, there are 2 new accounts, ACC06 and ACC07 which also gets loaded.
Finally on 5th April, we load existing accounts which have change in sale nos from their last value.

Now, I have to do a Daily MIS reporting and the result should be as follows, considering All my Accounts are Active as on 5th April 2019.

enter image description here

NO OF ACCOUNTS is actually the count of the Active Accounts at the end of each Day.

The above list Report 1, I was able to achieve using the following sub-query using Cognos Query/SQL items in Report Studio:

SELECT  DISTINCT D1.DAY, (SELECT COUNT(DISTINCT D2.ACCN_NO) FROM
DAILY_TABLE D2 WHERE D2.DAY <= D1.DAY) AS NO_OF_ACCOUNTS FROM
DAILY_TABLE D1 GROUP BY D1.DAY

Now, my requirement is to generate the following crosstab with a cut on the Gender.

enter image description here

Best Regards


Solution

  • you can split the totals easy by self joins, but I dont get how the no of accounts is setup. You will have to explain better.

    To split up the sales you can use this

    declare @sales table (salesday date, account varchar(5), sales int, gender varchar(10))
    
    insert into @sales (salesday, account, sales, gender)
    values ('20190401', 'ACC01', 5000, 'MALE'),
           ('20190401', 'ACC02', 6000, 'FEMALE'),
           ('20190401', 'ACC03', 7000, 'FEMALE'),
           ('20190401', 'ACC04', 8000, 'MALE'),
           ('20190402', 'ACC01', 7500, 'MALE'),
           ('20190402', 'ACC02', 4000, 'FEMALE'),
           ('20190402', 'ACC03', 10000, 'FEMALE'),
           ('20190402', 'ACC04', 20000, 'MALE'),
           ('20190403', 'ACC01', 8500, 'FEMALE'),
           ('20190403', 'ACC05', 3500, 'FEMALE'),
           ('20190404', 'ACC02', 9500, 'FEMALE'),
           ('20190404', 'ACC06', 3600, 'FEMALE'),
           ('20190404', 'ACC07', 4800, 'MALE'),
           ('20190405', 'ACC01', 15000, 'FEMALE'),
           ('20190405', 'ACC03', 12500, 'FEMALE')
    
    select s.salesday,
           sum(sm.sales) as sales_male,
           sum(sf.sales) as sales_female
    from   @sales s
      left join @sales sm on s.salesday = sm.salesday
                         and s.account = sm.account
                         and sm.gender = 'MALE'
      left join @sales sf on s.salesday = sf.salesday
                         and s.account = sf.account
                         and sf.gender = 'FEMALE'
    group by s.salesday
    order by 1
    

    the result will be

    salesday    sales_male  sales_female    
    --------    ----------  ------------    
    2019-04-01  13000       13000   
    2019-04-02  27500       14000   
    2019-04-03  null        12000   
    2019-04-04  4800        13100   
    2019-04-05  null        27500