Results 1 to 18 of 18

Thread: Randomizing database records

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Feb 2006
    Posts
    27

    Randomizing database records

    Hello

    Can anyone tell me which is the best method (or the code) for randomizing database records? The selected record, after randomization, is to be placed in a text box. I am using VB6 and Access 97.

    Thanks

  2. #2
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    Re: Randomizing database records

    Is there a field (hopefully numeric field) that could be used as a key in randomizing?

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Feb 2006
    Posts
    27

    Re: Randomizing database records

    Yes the Primary key id is numeric

    Thanks

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Randomizing database records

    One possible solution: If you want to return complete recordset or a subset, query the DB returning the record ids. Size a Long array of the recordcount and populate the array with the record ids. Then pass the array to a routine similar to following. The array will be randomized when it returns. The array are your randomized record ids, so to return one from the db, either query on the value in the array or if an existing recordset was maintained, use .Find to locate the random record
    Code:
    Private Function ShuffleExistingArray(inArray() As Long) As Boolean
    
        ' inArray must be a populated 1D array. Any LBound can be used
        
        Dim X As Long, rndNr As Long
        Dim tmpArray() As Long
        Dim lOffset As Long, nrItems As Long
        
        On Error GoTo EH
        tmpArray = inArray                              ' copy array structure
        lOffset = LBound(tmpArray)                      ' get its LBound
        nrItems = Abs(UBound(tmpArray) - lOffset)       ' calc nr of array items in ref to 0-LBound
        For X = nrItems To 0 Step -1                    ' begin randomly filling output array
            rndNr = Int(Rnd * (X + 1)) + lOffset        ' get rnd Index from temp array
            inArray(X + lOffset) = tmpArray(rndNr)      ' add to output array
            tmpArray(rndNr) = tmpArray(X + lOffset)     ' swap last array Index with selected array Index
        Next
        ShuffleExistingArray = True                     ' done
            
    EH:
        If Err Then
            MsgBox Err.Description, vbOKOnly
            Err.Clear
            inArray = tmpArray
        End If
    End Function
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Re: Randomizing database records

    Quote Originally Posted by LaVolpe
    One possible solution: If you want to return complete recordset or a subset, query the DB returning the record ids. Size a Long array of the recordcount and populate the array with the record ids. Then pass the array to a routine similar to following. The array will be randomized when it returns. The array are your randomized record ids, so to return one from the db, either query on the value in the array or if an existing recordset was maintained, use .Find to locate the random record
    Code:
    Private Function ShuffleExistingArray(inArray() As Long) As Boolean
    
        ' inArray must be a populated 1D array. Any LBound can be used
        
        Dim X As Long, rndNr As Long
        Dim tmpArray() As Long
        Dim lOffset As Long, nrItems As Long
        
        On Error GoTo EH
        tmpArray = inArray                              ' copy array structure
        lOffset = LBound(tmpArray)                      ' get its LBound
        nrItems = Abs(UBound(tmpArray) - lOffset)       ' calc nr of array items in ref to 0-LBound
        For X = nrItems To 0 Step -1                    ' begin randomly filling output array
            rndNr = Int(Rnd * (X + 1)) + lOffset        ' get rnd Index from temp array
            inArray(X + lOffset) = tmpArray(rndNr)      ' add to output array
            tmpArray(rndNr) = tmpArray(X + lOffset)     ' swap last array Index with selected array Index
        Next
        ShuffleExistingArray = True                     ' done
            
    EH:
        If Err Then
            MsgBox Err.Description, vbOKOnly
            Err.Clear
            inArray = tmpArray
        End If
    End Function
    If an error occurs you'd return an array with duplicated items... just select random array elements and swap them within same array.

  6. #6
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Randomizing database records

    Thanx for the tip. Simply removing the line: inArray = tmpArray from the EH: section would suffice. The only error would be lack of memory to build the tmpArray, which if it happens would occur before loop starts and the inArray in the EH section should not be allowed to be modified then.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  7. #7
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Re: Randomizing database records

    Please refer to post #24 by Logophobic to minimize bias in randomization http://www.vbforums.com/showthread.p...andomize+array

  8. #8
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    Re: Randomizing database records

    Firstly, you don't need to use a second array to suffle a given array.
    That will be inefficient with a large array. To suffle an array I will do this:
    Code:
    Function SuffleArray(ByRef inArray As Variant) As Boolean
       Dim i As Long
       Dim j As Long
       Dim iMin As Long
       Dim iMax As Long
       Dim vTemp As Variant
       
       If IsArray(inArray) Then
          iMin = LBound(inArray)
          iMax = UBound(inArray)
          Randomize
          For i = iMin To iMax
             j = Int((iMax - iMin + 1) * Rnd()) + iMin
             vTemp = inArray(i)
             inArray(i) = inArray(j)
             inArray(j) = vTemp
          Next
          SuffleArray = True
       End If
    End Function
    Secondly, no need to build a random array to get a random record from a table. This is my way:
    1. Open a DAO or ADO recordset : rst)
    2. Get RecordCount of rst : n -- use rst.MoveLast if required
    3. To get a random record:

    • Offset = Int(n * Rnd()) -- between 0 and n-1
    • rst.MoveFirst
    • rst.Move Offset
    • Read record data

  9. #9
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Randomizing database records

    anhn, I like your tweaks to the shuffle routine. The array method allows entire "list" to be shuffled without repeating. The second solution allows potential of repeating records. Depending on user's needs, they have choices.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  10. #10
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    Re: Randomizing database records

    Another method: Randomly sort the recordset.

    Open a DAO or ADO recordset based on the below SQL:
    SQL = "SELECT Table1.*, FROM Table1 ORDER BY Rnd()"

    Now you can get data of one record at a time from the top to the bottom of the recordset that is already in a random order.

    Edit: This method may not work because Rnd() has the same value for all records. Need to tweak some more.

    Edit2: It may work if we pass RecordID to Rnd():
    SQL = "SELECT Table1.*, FROM Table1 ORDER BY Rnd(Table1.RecordID)"
    Last edited by anhn; Jan 9th, 2008 at 11:52 PM.

  11. #11
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Re: Randomizing database records

    Behaviour of Rnd() or similar database function is database dependent... it won't work with access cause same value is returned for all records while seeding introduces bias.

  12. #12
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    Re: Randomizing database records

    Quote Originally Posted by leinad31
    Behaviour of Rnd() ... while seeding introduces bias.
    I think bias is not a big deal in this case. I just thought a way like that.
    It's good if someone input some tweaks to make it works as simple as possible.

  13. #13
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Re: Randomizing database records

    In retrospect, he wasn't very clear of his requirements. Such as if repetitive selection is allowed, or single selection until all numbers are exhausted, or how many random samples he will be retrieving from the population, etc.

    It would be best to wait for his response and refrain for the time being from lengthening this thread with more code/posts.

  14. #14

    Thread Starter
    Junior Member
    Join Date
    Feb 2006
    Posts
    27

    Re: Randomizing database records

    Hello again.

    Thank you for your replies.

    Leinad31 asked for some further information regarding the purpose of the query. We want to be able, from time to time, to select between one and five of our customers for investigative purposes. It doesn't matter if the same customer is selected again at a later date.

  15. #15
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Randomizing database records

    RAND() in MS SQL will never work in a SELECT statement - notice this

    Code:
    select rand(),* from ledtype_t
    It returns

    Code:
                           LedType LedTypeDesc      Hierarchy                      TDate
    ---------------------- ------- ---------------- ------------------------------ -----------------------
    0.204834390892421      AP      Accounts Payable                                NULL
    0.204834390892421      BB      Budget Book      D                              NULL
    0.204834390892421      BP      Budget Priors    G                              NULL
    0.204834390892421      BR      Revised Budget   F                              NULL
    0.204834390892421      BT      Budget Transfer  F                              NULL
    0.204834390892421      BU      Beginning Budget G                              NULL
    0.204834390892421      GP      G/L Priors       H                              NULL
    0.204834390892421      HC      Hand Checks      L                              NULL
    0.204834390892421      IN      Invoices         L                              NULL
    0.204834390892421      JE      Journal Entry    J                              NULL
    0.204834390892421      LQ      Liquidation      L                              NULL
    0.204834390892421      OC      Other Charges    M                              NULL
    0.204834390892421      OR      Other Receipts   R                              NULL
    0.204834390892421      PC      Payroll Charges  N                              NULL
    0.204834390892421      PO      Purchase Order   V                              NULL
    0.204834390892421      PP      Previous PO      V                              NULL
    0.204834390892421      PX      Adjust PO        V                              NULL
    0.204834390892421      RQ      Requisition      W                              NULL
    0.204834390892421      TH      Threshold        D                              NULL
    0.204834390892421      VD      Void Check/Inv                                  NULL
    
    (20 row(s) affected)
    The RAND() is evaluated once prior to the building of the working resultset. Each row gets the exact same value.

    I've seen suggestions to place RAND() into a USER DEFINED FUNCTION with MS SQL - I think by doing that it gets evaluated row by row.

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  16. #16
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    Re: Randomizing database records

    @szlamany, The same thing happens in Access as said in Post#10. It also won't work with a UDF.
    Quote Originally Posted by anhn
    Edit: This method may not work because Rnd() has the same value for all records. Need to tweak some more.

    Edit2: It may work if we pass RecordID to Rnd():
    SQL = "SELECT Table1.*, FROM Table1 ORDER BY Rnd(Table1.RecordID)"

  17. #17
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Re: Randomizing database records

    Quote Originally Posted by Bomber2006
    Hello again.

    Thank you for your replies.

    Leinad31 asked for some further information regarding the purpose of the query. We want to be able, from time to time, to select between one and five of our customers for investigative purposes. It doesn't matter if the same customer is selected again at a later date.
    If there are no gaps in the sequence of your primary key then get "SELECT MIN(pk), MAX(pk) FROM yourTable" first, then generate 3-5 random numbers into a CSV using VB Rnd(), and finally "SELECT columns FROM yourTable WHERE pk IN (" & csv & ") " to get random records.

    If there are gaps in the pk series (possibility that random number generated is a non-existent key) then you can simply retrieve more than you'll normally need, e.g. 10 records, and get your 3-5 records from that set.
    Last edited by leinad31; Jan 10th, 2008 at 07:39 AM.

  18. #18
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Randomizing database records

    @anhn - apparently you cannot put RAND() into a UDF - it's non determistic so it's not valid.

    But I guess you can put it in a VIEW and then reference the VIEW in the UDF - here's a link that discusses that

    http://www.vbforums.com/showthread.p...14#post2148414

    But of course this is all for MS SQL...

    A concept you can use for any database would be:

    1) Determine the number of rows in the table - SELECT COUNT(*) will do that
    2) Use RND() from the client side - with the number of row value - to determine which record you want
    3) Do a query something like this to get that one record

    Code:
    Select Top 1 * 
        From (Select Top {TheRandomRowFoundinStep2} *
                      From SomeTable Order by PriKey Desc) "XYZ"
    The sub-query gets only the number of rows determined in step 2 to offer up the random row of choice.

    Order by PRIKEY Desc will put the "last" record in that sequence first.

    Select Top 1 will get just that record.

    You can probably do something in the sub-query to get just the PRIKEY values and select WHERE PRIKEY=(...) that - lots of ways to handle this.

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width