UFN_MKTSEGMENTATIONSEGMENT_GETOFFERCOUNT

Return

Return Type
int

Parameters

Parameter Parameter Type Mode Description
@SEGMENTID uniqueidentifier IN
@TESTSEGMENTID uniqueidentifier IN
@TOTALOFFERS int IN

Definition

Copy


create function dbo.[UFN_MKTSEGMENTATIONSEGMENT_GETOFFERCOUNT]
(
  @SEGMENTID uniqueidentifier,
  @TESTSEGMENTID uniqueidentifier,
  @TOTALOFFERS integer
)
returns integer
as
  begin
    declare @OFFERS integer = @TOTALOFFERS;

    declare @TESTSEGMENTOFFERS table (
      [ID] uniqueidentifier not null,
      [SEQUENCE] integer not null,
      [FRACTIONNUMERATOR] integer,
      [FRACTIONDENOMINATOR] integer,
      [OFFERS] integer not null
    );

    declare @ID uniqueidentifier;
    declare @TESTSAMPLESIZE integer;
    declare @TESTSAMPLESIZETYPECODE tinyint;
    declare @TESTSEQUENCE integer;
    declare @FRACTION nvarchar(10);
    declare @SLASH integer;
    declare @FRACTIONNUMERATOR integer;
    declare @FRACTIONDENOMINATOR integer;
    declare @SAMPLESIZEOFFER integer;
    declare @ALLTESTSEGMENTSUSEPERCENT bit = 1;
    declare @ALLTESTSEGMENTSUSEFRACTION bit = 1;

    declare TESTSEGMENTCURSOR cursor local fast_forward for
      select
        [ID],
        [SAMPLESIZE],
        [SAMPLESIZETYPECODE],
        [SEQUENCE],
        [FRACTION]
      from dbo.[MKTSEGMENTATIONTESTSEGMENT]
      where [SEGMENTID] = @SEGMENTID
      order by [SEQUENCE];

    open TESTSEGMENTCURSOR;
    fetch next from TESTSEGMENTCURSOR into @ID, @TESTSAMPLESIZE, @TESTSAMPLESIZETYPECODE, @TESTSEQUENCE, @FRACTION;

    while (@@FETCH_STATUS = 0)
      begin
        if @TESTSAMPLESIZETYPECODE <> 0 -- percent

          set @ALLTESTSEGMENTSUSEPERCENT = 0;

        if @TESTSAMPLESIZETYPECODE = 2 -- fraction

          begin
            set @SLASH = charindex('/', @FRACTION);

            if @SLASH > 0
              begin
                set @FRACTIONNUMERATOR = cast(substring(@FRACTION, 1, @SLASH - 1) as integer);
                set @FRACTIONDENOMINATOR = cast(substring(@FRACTION, @SLASH + 1, 10) as integer);
              end
            else
              begin
                -- invalid segment sample size fraction, but we can't force raise an error here, so just zero it out and let it get a divide-by-zero error below

                set @FRACTIONNUMERATOR = 0;
                set @FRACTIONDENOMINATOR = 0
              end
          end
        else
          begin
            set @ALLTESTSEGMENTSUSEFRACTION = 0;
            set @FRACTIONNUMERATOR = null;
            set @FRACTIONDENOMINATOR = null;
          end

        set @SAMPLESIZEOFFER = (case @TESTSAMPLESIZETYPECODE
                                when 0 then -- percent 

                                  (@TOTALOFFERS * (cast(@TESTSAMPLESIZE as decimal(5,2)) / 100))
                                when 1 then -- records 

                                  (case when @TESTSAMPLESIZE < @OFFERS then @TESTSAMPLESIZE else @OFFERS end)
                                when 2 then -- fraction

                                  floor(@TOTALOFFERS * (@FRACTIONNUMERATOR / cast(@FRACTIONDENOMINATOR as numeric(30, 20))))
                                end);

        -- the offers can only be the minimum number of records left after taking out all test segments above this one

        set @SAMPLESIZEOFFER = (case when @SAMPLESIZEOFFER < @OFFERS then @SAMPLESIZEOFFER else @OFFERS end);
        set @OFFERS -= @SAMPLESIZEOFFER;

        insert into @TESTSEGMENTOFFERS (
          [ID],
          [SEQUENCE],
          [FRACTIONNUMERATOR],
          [FRACTIONDENOMINATOR],
          [OFFERS]
        ) values (
          @ID,
          @TESTSEQUENCE,
          @FRACTIONNUMERATOR,
          @FRACTIONDENOMINATOR,
          @SAMPLESIZEOFFER
        );

        fetch next from TESTSEGMENTCURSOR into @ID, @TESTSAMPLESIZE, @TESTSAMPLESIZETYPECODE, @TESTSEQUENCE, @FRACTION;
      end

    close TESTSEGMENTCURSOR;
    deallocate TESTSEGMENTCURSOR;

    if exists (select top 1 1 from @TESTSEGMENTOFFERS)
      begin
        declare @NEEDTODISTRIBUTE bit = 0;

        if @ALLTESTSEGMENTSUSEPERCENT = 1
     begin
            -- add up all the percentages to see if they add up to 100%

            if (select sum([SAMPLESIZE]) from dbo.[MKTSEGMENTATIONTESTSEGMENT] where [SEGMENTID] = @SEGMENTID) = 100
              set @NEEDTODISTRIBUTE = 1;
          end

        else if @ALLTESTSEGMENTSUSEFRACTION = 1
          begin
            -- add up all the fractions to see if they add up to 1

            declare @RESULTNUMERATOR bigint = 0;
            declare @COMMONDENOMINATOR bigint = 1;

            declare FRACTIONADDCURSOR cursor local fast_forward for
              select [FRACTIONNUMERATOR], [FRACTIONDENOMINATOR]
              from @TESTSEGMENTOFFERS;

            open FRACTIONADDCURSOR;
            fetch next from FRACTIONADDCURSOR into @FRACTIONNUMERATOR, @FRACTIONDENOMINATOR;

            while (@@FETCH_STATUS = 0)
              begin
                set @RESULTNUMERATOR = (@RESULTNUMERATOR * @FRACTIONDENOMINATOR) + (@FRACTIONNUMERATOR * @COMMONDENOMINATOR);
                set @COMMONDENOMINATOR = @COMMONDENOMINATOR * @FRACTIONDENOMINATOR;

                fetch next from FRACTIONADDCURSOR into @FRACTIONNUMERATOR, @FRACTIONDENOMINATOR;
              end

            close FRACTIONADDCURSOR;
            deallocate FRACTIONADDCURSOR;

            -- check if the fractions add up to 1

            if @RESULTNUMERATOR = @COMMONDENOMINATOR
              set @NEEDTODISTRIBUTE = 1;
          end

        -- now distribute the remaining records across the test segments in reverse order

        if @NEEDTODISTRIBUTE = 1
          begin
            declare @REMAININGOFFERS integer = (select @TOTALOFFERS - sum([OFFERS]) from @TESTSEGMENTOFFERS);

            declare DISTRIBUTECURSOR cursor local fast_forward for
              select [ID], [OFFERS]
              from @TESTSEGMENTOFFERS
              order by [SEQUENCE] desc;

            open DISTRIBUTECURSOR;
            fetch next from DISTRIBUTECURSOR into @ID, @OFFERS;

            while (@@FETCH_STATUS = 0 and @REMAININGOFFERS > 0)
              begin
                update @TESTSEGMENTOFFERS set
                  [OFFERS] = [OFFERS] + 1
                where [ID] = @ID;

                set @REMAININGOFFERS -= 1;

                fetch next from DISTRIBUTECURSOR into @ID, @OFFERS;  
              end

            close DISTRIBUTECURSOR;
            deallocate DISTRIBUTECURSOR;
          end
      end

    if @TESTSEGMENTID is null
      -- get the offers left over for the parent segment

      select
        @OFFERS = (@TOTALOFFERS - isnull(sum([OFFERS]),0))
      from @TESTSEGMENTOFFERS;
    else
      -- get the offers for the individual test segment

      select
        @OFFERS = [OFFERS]
      from @TESTSEGMENTOFFERS
      where [ID] = @TESTSEGMENTID;  

    return @OFFERS;
  end