Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 
Anonymous
Not applicable

Splitting the data - On the way to granularity

Hello community,

I have a really tricky problem:

One Table has State-Information (Field lState)

This state has a start time and a end time.

lStatetStarttEndDuration
122345420121126 11:04:3320121126 11:10:406 min
122345520121126 06:00:0020121127 13:00:001 d 7 h

I would like to achive a more detailed granularity:

I have three time zones per day:

TZ1: 06:00:00 - 14:00:00

TZ2: 14:00:00 - 22:00:00

TZ3: 22:00:00 - 06:00:00 (on the next day)

The split should lead to the following output:

IDlStatetStarttEndDurationDayTimeZone
1122345420121126 11:04:3320121126 11:10:406 min20121126TZ1
2122345520121126 06:00:0020121126 14:00:008 h20121126TZ1
3122345520121126 14:00:0020121126 22:00:008 h20121126TZ2
4122345520121126 22:00:0020121127 06:00:008 h20121126TZ3
5122345520121127 06:00:0020121127 13:00:007 h20121127TZ1

For sure I'll need some for next loops , but as I'm quite new to QlikView this is a too big fish for me.

Maybe somebody is interested in solving this nice problem or has already solved a similar problem.

Any help is welcome

Cheers

//chesterluck

15 Replies
Anonymous
Not applicable
Author

lMacStaRefShiftIDStartEndDurationtBegintEndTZTZStartTZEnd
15687141102.06.2012 11:00:0002.06.2012 14:00:003:00:0002.06.2012 11:00:0002.06.2012 21:55:18102.06.2012 06:00:0002.06.2012 14:00:00

End and TZEnd sould be 13:59:59

The second shift is missing and should be

15687141 - 2 -  02.06.2012 14:00:00   -  02.06.2012 21:55:18 - 9:55:18 - 02.06.2012 11:00:00 - 02.06.2012 21:55:18 - 2 - 02.06.2012 14:00:00 - 02.06.2012 21:59:59

swuehl
MVP
MVP

Yep, it's never a good idea to compare two floating point values 😉

To make my approach stable, we need to add a small amount of time (say 1 ms) to the one end of the WHILE comparison:

...

while floor(tStart,1/3,1/4) + (iterno()-1)/3 < floor(tEnd,1/3,1/4)+interval#(1,'fff');

Anonymous
Not applicable
Author

So the problem is that at the end of a while loop the comp might still calc and the while already goes further?? was that the problem??

I let you know whether its running smooth now

thx a lot already

Anonymous
Not applicable
Author

Ok, it works fine..

I have a last question:

Where should I split a quantity field (Number of parts) - during the split or can i do it after.

I started to do it and im basically just counting the persentage of a Timezonepart to the complete StateTime and then i multiply it with the Quantity nr.

round((DurationStatePart/DurationState)*ShotsAll) as NumberOfShotsInTheStatePart

sth like this.

The problem iswhen the numbers are like this:

20

20,5

19,5

While rounding I would get one part more....

any idea?

swuehl
MVP
MVP

>So the problem is that at the end of a while loop the comp might still calc and the while already goes further?? was that the problem??

Hm, no, I don't think so. The problem is that floating point calculations might be a bit off due to the internal representation even when the calculation is logically / mathematically correct.

So something like

floor(tStart,1/3,1/4) + 1/3 <= floor(tEnd,1/3,1/4)

might return false even (with your numbers for tStart and tEnd entered), even when it should return true, because floating point arithmetic calculations were not 100% correct, just a little off (for example, 1/3 cannot be represented correctly in the used base system).

[edit]: Even this should be more stable than my first version, though in a mathmetical sense, both should be equal:

...

while floor(tStart+ (iterno()-1)/3 ,1/3,1/4)  <= floor(tEnd,1/3,1/4);

>While rounding I would get one part more.... any idea?

So your requirement is that the sum of your rounded numbers equals ShotsAll, right? So you need an unbiased tie-breaking when rounding.

I don't think there is the one and only one correct answer to this, maybe you can try something like

TEST:

LOAD recno() as ID,

    TEST,

    floor(TEST) as FLOOR,

    TEST - floor(TEST) as DIFF

INLINE [

TEST

20

20.5

19.5

18.5

21.5

18.6

19.4

];

JOIN LOAD

    round(sum(TEST)-SUM(FLOOR)) as TOSHARE

Resident TEST;

LOAD ID,

    RANGESUM(FLOOR, if(recno()<=TOSHARE,1,0)) as RESULT 

Resident TEST order by DIFF desc, FLOOR desc;

Anonymous
Not applicable
Author

well I tried your solution with

 

while

floor(tBegin,1/3,1/4) + (iterno()-1)/3 <= floor(tEnd,1/3,1/4)
+
interval#

(1,'fff');

and it seems to be stable (I builded Sum over 50000 rows)

Did I understand it right that this solution :

while floor(tStart+ (iterno()-1)/3 ,1/3,1/4)  <= floor(tEnd,1/3,1/4);

might be even more stable??

cheers

chesterluck