Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Getting Missing Numbers Between Two Values in a Table
Message
De
13/11/2017 15:04:31
 
 
À
13/11/2017 07:35:05
Information générale
Forum:
Visual FoxPro
Catégorie:
Codage, syntaxe et commandes
Versions des environnements
Visual FoxPro:
VFP 9 SP2
OS:
Windows 7
Database:
Visual FoxPro
Application:
Desktop
Divers
Thread ID:
01655491
Message ID:
01655569
Vues:
74
>Recno() is not bad as speeds go - remember setting relation not via index, but recno() in child table back in 386/486 days?

That's the "thing I learned about VFP" for today ;) It's been a long time since I used SET RELATION (last century, I believe). I never used the numeric variation, I always indexed the child table.

>Could give you speedups between 30 and 55% when you ditched the index file ;-)
>
>Depends a lot on how you need the result (table) and what processing follows.
>A variation of the theme would be to not create a result cursor, but to delete the existing numbers/records/recno() from the alltable and to recall all before each run.

Another clever idea!

>As each deletion mark is also only 1 char wide, much less write traffic to the physical medium. Deleting on a table of integers incurs the same amount of write traffic as on the recno() of single chars (both non-null), but again the basic table size for int columns is larger - which translates back into more head movement - bad on traditional disk, less worrysome on SSD as random IO has less perf problems there.
>
>Also more records per physical sector/cluster in the non-int case, and I guess that would translate perhaps into less physical writes triggered via the OS, but that is a gut guess - although the total # of sectors written probably is less in the char/recno()-table setup ;-))
>
> Thinking on more basic computerese building blocks is today not needed any more ;-)

Exactly. The point about less I/O due to deletemark vs actual deletion is valid regardless of environment. But the other stuff... these days pretty much all my VFP work is in VMs. The host typically has a lot of RAM and write caching enabled so the nuts & bolts of getting bytes to/from persistent storage are pretty well hidden.

>>Clever - but how would it work in practice? Is it possible to avoid RECNO() calls in the final SELECT - SQL?
>>
>>>Going all out to minimize space, a table of char[1] indexed on recno() and selecting the same would allow much larger ranges to fit into a cache ;-))
>>>
>>>>Definitely. A DBF + CDX of 10,000 integers totals about 95KB, which will fit in the cache of many modern CPUs (L2 or L3, if not L1) so it could be a big performance win in a recurring-calls scenario.
>>>>
>>>>>The OP reads to me that this is a recurring requirement, so I'd exchange space for time and create AllLarge as pre-indexed table and query the range established by min/max via where ;-))
>>>>>
>>>>>>>The Range may be Between 1 to 10000 and it is not necessary that 1 will in the top or 10000 will be at the bottom of the cursor.
>>>>>>>I need Missing Figures in a Cursor (Difference in Numbers=1)
>>>>>>
>>>>>>There is a way to do it via SQL - maybe not the fastest, but relatively simple and maintainable:
>>>>>>
>>>>>>* Assume your cursor with random values has an alias RandomVals
>>>>>>LOCAL ;
>>>>>>	lnMinVal ;
>>>>>>	, lnMaxVal ;
>>>>>>	, lnIx
>>>>>>
>>>>>>* Get lowest and highest values:
>>>>>>* Option 1: index RandomVals:
>>>>>>SELECT RandomVals
>>>>>>INDEX ON fObjectNo TAG fObjectNo
>>>>>>
>>>>>>GO TOP
>>>>>>m.lnMinVal = RandomVals.fObjectNo
>>>>>
>>>>>
>>>>>>GO BOTTOM
>>>>>>m.lnMaxVal = RandomVals.fObjectNo
>>>>>>
>>>>>>* Option 2: don't want to index RandomVals:
>>>>>>*!*	CALCULATE ;
>>>>>>*!*		MIN( fObjectNo ) ;
>>>>>>*!*		, MAX( fObjectNo ) ;
>>>>>>*!*		TO ;
>>>>>>*!*			m.lnMinVal ;
>>>>>>*!*			, m.lnMaxVal ;
>>>>>>*!*		IN RandomVals
>>>>>>
>>>>>>* Create another cursor with all possible values, both present and missing:
>>>>>>CREATE CURSOR AllVals ( iVal I )
>>>>>>
>>>>>>* Populate the cursor with all possible values between m.lnMinVal and m.lnMaxVal
>>>>>>FOR m.lnIx = m.lnMinVal TO m.lnMaxVal STEP 1
>>>>>>	INSERT INTO AllVals ( iVal ) VALUES ( m.lnIx )
>>>>>>
>>>>>>ENDFOR
>>>>>>
>>>>>>* Optional - index AllVals to help speed up the final SELECT - SQL:
>>>>>>SELECT AllVals
>>>>>>INDEX ON iVal TAG iVal
>>>>>>
>>>>>>* Get missing values:
>>>>>>SELECT ;
>>>>>>	iVal ;
>>>>>>	FROM AllVals ;
>>>>>>	WHERE iVal NOT IN ;
>>>>>>		( SELECT fObjectNo FROM RandomVals ) ;
>>>>>>	INTO CURSOR MissingVals ;
>>>>>>	ORDER BY iVal
>>>>>>
>>>>>>* Cleanup:
>>>>>>USE IN SELECT( "AllVals" )
>>>>>>
Regards. Al

"Violence is the last refuge of the incompetent." -- Isaac Asimov
"Never let your sense of morals prevent you from doing what is right." -- Isaac Asimov

Neither a despot, nor a doormat, be

Every app wants to be a database app when it grows up
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform