Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Problem with the function
Message
 
 
To
26/10/2000 12:08:44
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Miscellaneous
Thread ID:
00434138
Message ID:
00434787
Views:
18
Ok, this is the modified version:
***************************************************************************
*  Description.......: GetMedianValue - returns median value from a specified table
*  Calling Samples...: GetMedianValue('curPrice','LstSlPrice')
*  Parameter List....: pcTableName, pcField, pcWhere
*  Created by........: Daniel Rouleau  #025397 - original idea
*  Modified by.......: Nadya Nosonovsky 10/25/2000 01:30:02 PM
*****************************************************************************
* Returns median value or .f. for unsuccessful cases
lparameters pcTableName, pcField, pcWhere

* pcTableName - name of the table or already opened cursor, which should be processed
* pcFiled     - name of the field, which used in calculation, price, for example
* pcWhere - where expression suitable for macro
* Both parameters are optional, if they are not specified, current working alias is used and price field
** Check parameter first
if empty(pcTableName) or vartype(pcTableName)<>'C'
     pcTableName=alias() && Current open alias
     if empty(pcTableName) && No current table
          return .f.
     endif
endif
if empty(pcField) or vartype(pcField)<>'C'
     pcField=upper('price')
else
     pcField=upper(pcField)
endif
if empty(pcWhere) or vartype(pcWhere)<>'C'
     pcWhere=''
endif
local lnMiddleRecord, lcCursor, lnOldSelect, lnMedianValue
lnOldSelect=select() && Save current area
lcCursor='cur'+sys(2015) && Unique name
if used(lcCursor) && Should never happen
   use in (lcCursor)
endif   

select &pcField from (pcTableName) ;
       where &pcWhere ; 
       into cursor (lcCursor) order by 1 descending
if _tally>3
     lnMiddleRecord=floor(_tally/2)
else
     =messagebox('Number of records is less than 3. Can not calculate median...',48)
     return .f.
endif
if used(lcCursor)
     go top in (lcCursor)
     skip lnMiddleRecord in (lcCursor)
     lnMedianValue = evaluate(lcCursor + '.' + pcField)
     use in (lcCursor)
endif
select (lnOldSelect) && Return to the original area
return lnMedianValue
>Nadya:
>
>>
>BTW, in my original program I replaced goto nMiddleRecord with skip nMiddleRecord-1 and now it works also fine. I compared speed in both programs and my original program works faster, though has more lines of code...
>>
>
>I thought a little more about this and I came up with this:
> lcCursor = Sys(2015)
> If Used(lcCursor) Then
> Use In (lcCursor)
> EndIf
>
> Select &lcField From (lcTable) Into Cursor (lcCursor) Order By 1 Asc
>
> If Used(lcCursor) Then
> Go Top In (lcCursor)
> Skip Ceiling(RecCount(lcCursor)/2) In (lcCursor)
> lnRetVal = Evaluate(lcTable + '.' + lcField)
> Use In (lcCursor)
> EndIf
>
>I replaced Into Array with Into Cursor because of memory problems with large tables (Error 209). I still would not use your first solution because:
> * Pointers have to be reset. This may not so trivial if there are relations
> involved.
> * Filter has to be removed and reset.
> * Index Tag has to be changed and reset which may affect some relations.
> * Reccount is the total number of records in the table, which may include some
> deleted records.
> * The tag may not exists and if it doesn't, grabbing exclusive use to the
> table may not be realistic.
>
>You don't have to deal with these problems and you Select .. Into Cursor. Furthermore, the query will run faster if you have a tag on the specified field.
>
>Hope this helps clarify the situation,
>
>Daniel
If it's not broken, fix it until it is.


My Blog
Previous
Reply
Map
View

Click here to load this message in the networking platform