2016-08-05 32 views
0

Ich versuche, eine schnellere Möglichkeit zu finden, meine Mediane in Access zu berechnen. Sie können den folgenden Code sehen, in dem jeweils ein Artikelcode abgefragt, sortiert und dann der Median berechnet wird. Manchmal gibt es 600 Artikelcodes und diese Artikel können jeweils über 1000 Basen zugeordnet werden. Die spezielle Tabelle, mit der ich arbeite, hat zum Beispiel 150.000 Datensätze und es geht wirklich langsam. Gibt es eine bessere Möglichkeit, den Median aller Datensätze gleichzeitig zu berechnen, im Gegensatz zu einem Artikelcode gleichzeitig?MS Access VBA: Berechnen Median ohne Iterieren durch Datensätze

Function FIncPercentile(ByVal posCode As Single, ByVal k As Single, ByVal tbl As String) As Variant 

Dim rstRec As Recordset 
Dim db As Database 
Dim n As Integer 
Dim i As Single 
Dim res, d1, d2 As Currency 

' Create recordset from query 
Set db = CurrentDb 
Set rstRec = db.OpenRecordset("SELECT Co, Base " & _ 
           "FROM " & tbl & " " & _ 
           "WHERE Code = " & pos & " " & _ 
           "ORDER BY Base ASC;") 

' Skip if there are no matches 
If IsNull(rstRec!base) Or rstRec.RecordCount = 0 Then 
    FBasePercentile = Null 
    Exit Function 
End If 

' Count records 
rstRec.MoveLast 
n = rstRec.RecordCount 
rstRec.MoveFirst 

' Calculate the index where k is the percentile 
i = n * k 

' Test the decimal and find value accordingly 
If i = Int(i) Then 
    rstRec.Move i - 1 
    d1 = rstRec!base 
    rstRec.MoveNext 
    d2 = rstRec!base 
    FIncPercentile = (d1 + d2)/2 
Else 
    i = Round(i + 0.5, 0) 
    rstRec.Move i - 1 
    FIncPercentile = rstRec!base 
End If 

End Function 
+0

haben Sie versucht, eine Datensatzgruppe für jede Tabelle durch Co, Basis geordnete Öffnung und in einer äußeren Schleife durch jede Co Iterieren der Median mit Filtern in einer inneren Schleife die Berechnung? – Beth

+0

Sie könnten wahrscheinlich die DMedian-Funktion und Beispiel von Microsofts Website https://msdn.microsoft.com/en-us/library/dd789431%28v=office.12%29.aspx anpassen - oder ist das, wo Sie Ihren Code haben? – dbmitch

+0

Wie viele eindeutige Tabellen - wenn es nur eine gibt - ich würde denken, dass Sie eine sofortige Zunahme sehen würden, indem Sie eine Parameterabfrage auf der Tabelle erstellen, wo Code der Parameter ist. Verwenden Sie den Parameter querydef, um das Recordset zu erstellen - anstelle von dynamischem SQL - UND stellen Sie sicher, dass Sie einen Index für Code und Base haben. – dbmitch

Antwort

2

Es gibt keine Median-Funktion in Access. Excel hat einen, aber ich glaube, es ist auf 30 Nummern beschränkt. Selbst wenn Sie also eine Automatisierungsfunktion verwenden wollten, glaube ich nicht, dass es für Ihren Fall funktionieren würde.

Ich denke, dass Sie eine spürbare Geschwindigkeitszunahme sehen können, indem Sie Ihre Funktion optimieren und Microsofts Jet Engine Ihre Abfrage vorkompilieren lassen.

  • Achten Sie darauf, die Basis und-Code haben Felder in der Tabelle indiziert (n)
  • erstellen Parameterabfrage mit Code, um das Kriterium Parameter mit [Was Code]
  • Optimieren Sie Ihre Funktion mit Cord-MIT-Konstrukt , erklärt Variablen und angepasst Feldtypen (Code = Long Integer ???)

Zeit es vor und nach diesen Änderungen alle und sehen, ob es irgendwelche spürbaren Unterschied ist

Ich korrigierte ein paar Tippfehler, die keine Tippfehler sind - und ich nehme an, dass CODE eine lange Ganzzahl ist - was wiederum falsch ist. Auch sind meine Änderungen vorangestellte ‚***************

CREATE Precompiled Parameterabfrage

Neue Query anlegen namens "qdfPrepMedian"

Kopieren/Einfügen SQL >>PARAMETERS [What Code] Long; SELECT Co, Base FROM <YourTableName> WHERE Code = [What Code] ORDER BY Base ASC;

Speichern Sie die Abfrage

Adjusted Function

Option Explicit 

'*********************** 
' changed posCode to Long 
'*********************** 
Function FIncPercentile(ByVal posCode As Long, ByVal k As Single, ByVal tbl As String) As Variant 

    '*********************** 
    ' CREATE/USE Precompiled Parameter Query 
    ' Create New Query called "qdfPrepMedian" 
    ' Copy/Paste SQL >> PARAMETERS [What Code] Long; SELECT Co, Base FROM <YourTableName> WHERE Code = [What Code] ORDER BY Base ASC; 

    Const QRY_BY_CODES As String = "qdfPrepMedian" 

    Dim qdf  As QueryDef 
    ' 
    '*********************** 

    Dim rstRec As Recordset 
    Dim db  As Database 
    Dim n  As Integer 
    Dim i  As Single 

    ' Declare all Currency variables on separate lines 
    ' Otherwise they will be variants 
    Dim res  As Currency 
    Dim d1  As Currency 
    Dim d2  As Currency 

    Set db = CurrentDb 

    '*********************** 
    ' Create readonly recordset from querydef 
    Set qdf = db.QueryDefs(QRY_BY_CODES) 
    qdf.Parameters("What Code") = posCode ' matches LONG variable passed to function 
    Set rstRec = qdf.OpenRecordset(dbOpenSnapshot, dbReadOnly) ' Readonly is sometimes faster 
    '*********************** 

    ' Use WITH rstRec 
    With rstRec 

     ' Skip if there are no matches 
     If IsNull(!base) Or .RecordCount = 0 Then 
     '*** Is this a type *** 
     ' FBasePercentile = Null 
     ' Should it BE 
      FIncPercentile = Null 
      Exit Function 
     End If 

     ' Count records 
     .MoveLast 
     n = .RecordCount 
     .MoveFirst 

     ' Calculate the index where k is the percentile 
     i = n * k 

     ' Test the decimal and find value accordingly 
     If i = Int(i) Then 
      .Move i - 1 
      d1 = !base 
      .MoveNext 
      d2 = !base 
      FIncPercentile = (d1 + d2)/2 
     Else 
      i = Round(i + 0.5, 0) 
      .Move i - 1 
      FIncPercentile = !base 
     End If 

    End With 

End Function 
+0

@Andre danke für die Verbesserung meiner Post. Ich kann die Änderungen nicht herausfinden.Ich dachte, ich hätte eine Art VB-Tag gesehen, aber es ist nicht sichtbar in der Post. Was muss ich beim nächsten Mal machen? – dbmitch

+1

Wechseln Sie in der Revisionshistorie zu 'side-by-side markdown', um die Änderung zu sehen. Ich habe '' eingefügt, siehe http://stackoverflow.com/editing-help#syntax-highlighting. Dies ist erforderlich, wenn ein beliebteres Sprach-Tag vorhanden ist (normalerweise 'sql'). Ich habe diese Zeile in meiner "SO Template-Datei", weil ich sie so oft brauche. :) – Andre

+0

Cool. Das wird viel helfen. Ich fing an, extra 'am Ende der Zeilen hinzuzufügen, um die ärgerlichen, endlosen Lichter der Kommentarzeilen loszuwerden. – dbmitch