Lorenzo Benaglia


Storie di un SQLlaro mannaro...
Archivio Posts
Anno 2010

Anno 2009

Anno 2008

Anno 2007

Anno 2006

Anno 2005
Calendario
novembre 2024
lmmgvsd
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

Ordinamento casuale in Microsoft Access

Questa sera nel rispondere ad una domanda apparsa sul newsgroup microsoft.public.it.sql che chiedeva come sia possibile generare un result set ordinato in modo casuale in Microsoft Access, mi è capitata in mano una vecchia risposta che diedi un paio di anni fa.
Nel rileggerla ho trovato interessante la soluzione proposta, così ho pensato di inserirla nel mio blog.
Vediamo di che si tratta.
In SQL Server è piuttosto semplice ottenere un result set ordinato in modo casuale, ad esempio specificando nella clausola ORDER BY la funzione NEWID() che per ogni riga del result set genera un nuovo valore.
In Access spesso si ricorre alla funzione Jet-SQL RND() (come riportato nell'articolo How to find N records in random order in Access 2002 della Knowledge Base) ma purtroppo questa funzione genera dei valori pseudo-casuali, ovvero casuali solo all'apparenza.
La verifica è presto fatta.
Immaginiamo di scrivere la query qryTop10Products e di memorizzarla nel database Northwind(Nwind.mdb):

SELECT TOP 10 ProductName
FROM Products
ORDER BY Rnd(ProductID)

1) Eseguendo la query, otterremo un certo ordinamento;
2) Eseguendola una seconda volta otterremo un ordinamento differente;
3) Chiudiamo Access e riapriamolo;
4) Eseguiamo nuovamente la tua query e... otterremo lo stesso ordinamento del punto 1;
5) Eseguendola una seconda volta e otterremo l'ordinamento del punto 2.

E così via...

Un workaround potrebbe essere quello di utilizzare una funzione Jet-SQL differente, passando alla query un parametro di input "casuale". 
Vediamo un esempio.

1) Come prima cosa ho modifichiamo la query qryTop10Products nel seguente modo:

PARAMETERS [Seed] IEEEDouble;
SELECT TOP 10 ProductName
FROM Products
ORDER BY SIN(ProductID * Seed);


2) Infine ho preparato la pagina Products.asp che richiama la query valorizzando il parametro Seed con l'ora corrente del webserver convertita in double e moltiplicata per 10.000:

<%@ Language="VBScript" %>
<%
Dim cmd
Dim rs


Const adCmdStoredProc = 4
Const adDouble = 5
Const adParamInput = 1
Const adUseClient = 3
Const adOpenStatic = 3
Const adLockReadOnly = 1


On Error Resume Next

' Creo un oggetto ADODB.Command che richiama la Query qryTop10Products
Set cmd = Server.CreateObject("ADODB.Com­mand")
With cmd
    .CommandType = adCmdStoredProc
    .CommandText = "qryTop10Products"
    .Parameters.Append .CreateParameter("Seed", adDouble, adParamInput, , cdbl(Time) * 10000)
    .ActiveConnection = "Provider=Microsoft.Jet.OLEDB.­4.0;Data Source=" & Server.MapPath("Nwind.mdb")
End With


' Creo un oggetto ADODB.Recordset client side
Set rs = CreateObject("ADODB.Recordset"­)
With rs
    .CursorLocation = adUseClient
    .CursorType = adOpenStatic
    .LockType = adLockReadOnly


    ' Apro il recordset
    .Open cmd


    ' Disconnetto il recordset
    Set .ActiveConnection = Nothing
End With


' Distruggo il Command
Set cmd = Nothing
%>
<HTML>
<META HTTP-EQUIV="Refresh" CONTENT="5; URL=http://localhost/products.asp">
<META HTTP-EQUIV="Expires" CONTENT="0">
<TITLE>
Top 10 Product list:
</TITLE>
<BODY>
<H1> Top 10 Product list: </H1>
<%
With rs
    Do Until .EOF
        Response.Write .Fields("ProductName").Value & "<BR>"
        .MoveNext
    Loop


    ' Chiudo il Recordset
    .Close
End With


' Lo distruggo
Set rs = Nothing
%>


</BODY>
</HTML>


Richiamando la pagina via browser noteremo che ogni 5 secondi verrà generata una vista di prodotti effettivamente casuale
Categoria: Access
giovedì, 23 giu 2005 Ore. 23.45
Statistiche
  • Views Home Page: 966.597
  • Views Posts: 715.144
  • Views Gallerie: 13.667.885
  • n° Posts: 300
  • n° Commenti: 314
Mappa





















Copyright © 2002-2007 - Blogs 2.0
dotNetHell.it | Home Page Blogs
ASP.NET 2.0 Windows 2003