Wer mit Datenbanken hantiert kommt das ein oder andere Mal in die Situation
Datensätze zählen zu müssen. Mit SQL eigentlich kein Problem. Etwas kniffliger
wird die Sache, wenn man ermitteln möchte wie oft ein Teil eines Feldinhaltes
in einer Tabelle vorkommt.
Ein Beispiel: fast alle Webs bieten ein Log in dem festgehalten wird, welche
Zugriffe stattgefunden haben. Dabei wird u.a. die IP-Adresse und der Host-Name
des Besuchers festgehalten. Möchte man nun eine Auswertung über die Host-Namen
erstellen, ist es sinnvoll nur den Domain-Namen und die Top-Level-Domain heranzuziehen,
da die Sub-Domains aufgrund der Zuweisung von dynamischen IP-Adressen bei den
meisten Providern immer anderes lauten. Beispielsweise lautet der Host-Name
eines Telekom-Kunden p1451708C.dip.t-dialin.net. Um nun zu erfahren wieviele
Besucher über die Telekom die Seite besuchen ist nur der Teil-String t-dialin.net
relevant.
Da in der Tabelle aber nur der gesamte String steht, muss der String an den
Punkten aufgeteilt werden, um anhand der letzten beiden Teile die gleichlautenden
Einträge in der Tabelle zu zählen. Mit SQL ist das zwar möglich, aber etwas
aufwendiger. Einfacher ist es über alle Datensätze der Tabelle zu gehen, den
relevanten Teil des Host-Namens auszuschneiden und diesen zu zählen. Aber wo
sollen die bereits aufgetretenen Einträge und der Zähler abgelegt werden? In
einem zweidimensionalen Array mit dem Host-Namen als erste und dem Zähler als
zweite Dimension.
Dimensionieren wir uns zunächst ein entsprechendes Sammel-Array und initialisieren
es mit zwei Dimensionen (0 und 1)
Dim arrHosts()
ReDim arrHosts(0, 1)
Als nächstes brauchen wir den Zugriff auf die entsprechende Tabelle über
ein ADO-Recordset, die wir anschließend mit einem Do...Loop
vom ersten bis zum letzten Datensatz durchlaufen:
... Datenbankverbindung aufbauen und Recordset initialisieren
Do Until rs.EOF
...
Loop
In dieser Schleife überprüfen wir für jeden Datensatz als erstes, ob in dem
zu verarbeitenden Host-Namen überhaupt ein Punkt vorkommt, nach dem wir den
String trennen können. Wenn ja, wird er mit der Split-Funktion in ein Hilfs-Array
zerlegt und die letzten beiden Teile in der Variable strHost
gespeichert. Wenn nein, dann wird der gesamte Host-Name verwendet:
If Instr(1, rs.Fields("HostName"), ".") > 0 then
arrTemp = Split(rs.Fields("HostName"), ".")
strHost = arrTemp(UBound(arrTemp) - 1) & "." & arrTemp(UBound(arrTemp))
Else
strHost = rs.Fields("HostName")
End if
Als nächstes müssen wir überprüfen, ob der Host-Name bereits in unserem Sammel-Array
arrHosts enthalten ist. Dies geschieht, in dem in
einer Schleife der Wert der ersten Dimension mit dem aktuellen Host-Namen verglichen
wird. Wird er gefunden, so wird der Wert der korrespondierenden zweiten Dimension
um eins erhöht und über die Variable bolFound gekennzeichnet,
dass der Host-Name bereits verarbeitet wurde:
For j = 0 To UBound(arrHosts)
If arrHosts(j, 0) = strHost Then
arrHosts(j, 1) = arrHosts(j, 1) + 1
bolFound = True
Exit For
Else
bolFound = False
End If
Next
Ist der Host-Name nicht bereits im Array enthalten, müssen wir nun zunächst
das Array für den neuen Eintrag erweitern. Leider ist es jedoch so, dass die
VBScript-eigene Funktion ReDim Preserve dies zwar
erledigen kann, aber immer nur für die letzte Dimension. Wir müssen jedoch an
die erste Dimension ein weiteres Feld anhängen! Da hilft nur eine
Zusatzprozedur, in der das Array einfach in ein neues umkopiert wird. Das
Original-Array wird hierbei ByRef übergeben.
Exkurs:
Public Sub ReDimEx(arrSource, intNewX, intNewY)
Dim arrTemp
Dim i, j
arrTemp = arrSource
ReDim arrSource(intNewX, intNewY)
For i = LBound(arrTemp, 1) To UBound(arrTemp, 1)
For j = LBound(arrTemp, 2) To UBound(arrTemp, 2)
If i <= intNewX And j <= intNewY Then
arrSource(i, j) = arrTemp(i, j)
End If
Next
Next
End Sub
Mit dieser Prozedur können wir nun den neuen Host-Namen an das Sammel-Array
anfügen:
If bolFound = False Then
Call ReDimEx(arrHosts, UBound(arrHosts, 1) + 1, UBound(arrHosts, 2))
arrHosts(UBound(arrHosts, 1) - 1, 0) = strHost
arrHosts(UBound(arrHosts, 1) - 1, 1) = 1
End If
Wurden alle Datensätze verarbeitet und ist die Datenbankverbindung wieder
geschlossen, können wir uns abschließend um die Darstellung der Array-Einträge
kümmern:
For i = 0 to Ubound(arrHosts, 1)
strHostName = arrHosts(i, 0)
strHostCount = arrHosts(i, 1)
... Darstellung z.B. in einer Tabellenzelle
Next