Mächtige Analysen: Frequent Itemsets

"Wer Produkt A gekauft hat, kauft in der Regel auch Produkt X.

Wie kann man zu solchen Aussagen kommen? Heute lesen Sie, wie die Oracle-Datenbank Ihnen beim Auffinden solcher Frequent Itemsets helfen kann. Eine Tabelle mit Umsatzdaten (SH.SALES) dient als Ausgangssituation. Das Datenbankschema SH ist in Ihrer Datenbank vorhanden, wenn beim Erstellen die Option Beispielschemata installieren ausgewählt wurde. Bevor Sie beginnen: Sorgen Sie dafür, dass Ihr Application Express-Workspace SELECT-Privilegien an den Tabellen SH.SALES, SH.CUSTOMERS und SH.PRODUCTS hat. Sie können das Beispiel natürlich auch mit Ihren eigenen Daten nachvollziehen.

Beginnen Sie mit einem einfachen Bericht ...

select 
c.cust_first_name || ' ' ||c.cust_last_name,
p.prod_name,
s.time_id
from sales s join customers c using (cust_id)
join products p using (prod_id)
where :P1_PROD_ID is null or prod_id = :P1_PRODID

In der SQL-Abfrage sehen Sie das Element :P1_PRODID. Legen Sie es also zusätzlich als Auswahlliste mit dem folgenden SQL-Kommando an:

select prod_name d, prod_id r from sh.products order by 1

Das Ergebnis sollte wie folgt aussehen:

Ausgangssituation: Bericht auf die Tabelle SH.SALES
Abb.1: Ausgangssituation: Bericht auf die Tabelle SH.SALES

Schauen Sie sich den Bericht nun für verschiedene Produkte an. Interessant wäre die Frage, welche Produktkombinationen vom gleichen Kunden am gleichen Tag gekauft wurden und ob es dabei Kombinationen gibt, die besonders häufig vorkommen. Bei Beantwortung dieser Frage hilft Ihnen das PL/SQL-Paket DBMS_FREQUENT_ITEMSETS. Es stellt zwei Tabellenfunktionen (Table-Functions) zur Verfügung:

  • FI_TRANSACTIONAL:
    Diese Funktion geht davon aus, dass jeder einzelne Produktverkauf in einer eigenen Tabellenzeile zu finden ist.
  • FI_HORIZONTAL:
    ... geht davon aus, dass die gesamte Transaktion (der Einkauf eines Kunden an einem Tag) ein einer Tabellenzeile zu finden ist - die einzelnen Elemente (die gekauften Produkte) sind dann in den Tabellenspalten zu finden.

Da die Tabelle SH.SALES eine Tabellenzeile für jeden einzelnen Produktverkauf enthält, wird die Funktion DBMS_FREQUENT_ITEMSET.FI_TRANSACTIONAL verwendet. Die Syntax zum Aufruf der Funktion ist wie folgt:

DBMS_FREQUENT_ITEMSET.FI_TRANSACTIONAL (
tranx_cursor IN SYSREFCURSOR,
support_threshold IN NUMBER,
itemset_length_min IN NUMBER,
itemset_length_max IN NUMBER,
including_items IN SYS_REFCURSOR DEFAULT NULL,
excluding_items IN SYS_REFCURSOR DEFAULT NULL)
RETURN TABLE OF ROW (
itemset [Nested Table of Item Type DERIVED FROM tranx_cursor],
support NUMBER,
length NUMBER,
total_tranx NUMBER);

Im folgenden sind die Parameter der Funktion beschrieben:

  • tranx_cursor:
    Dieser Parameter vom Typ REF CURSOR liefert zwei Ergebnisspalten zurück. Einen REF CURSOR versteht man am besten als SQL-Abfrage, die einer Funktion als Ganzes übergeben wird. Die erste Spalte der Abfrage enthält eine Transaktions-ID, die zweite das Element, welches ausgewertet werden soll.
    Die Transaktions-ID dürfte in den meisten Fällen eine Sitzungs-, Einkaufs- oder Kassenbon-ID sein. Da die Tabelle SH.SALES eine solche ID nicht enthält, konstruieren wir eine aus dem Datum und der Kunden-ID. Gesucht werden also Produktkombinationen, die von einem Kunden an ein- und demselben Tag bevorzugt gekauft wurden.
  • support_threshold:
    Dieser Parameter beantwortet die Frage, ab wann eine Produktkombination als besonders häufig (frequent) angenommen werden soll. Wenn in diesem Beispiel 0,05 angegeben wird, so werden Produktkombinationen, die in mehr als 5 Prozent der Fälle auftreten, als Ergebnis zurückgegeben.
  • itemset_length_min:
    Aus wieviel Produkten (Items) sollen die gefundenen Kombinationen mindestens bestehen?
  • itemset_length_max:
    Aus wieviel Produkten (Items) sollen die gefundenen Kombinationen maximal bestehen?
  • including_items:
    Hier kann wiederum ein REF CURSOR, welcher eine Liste mit Produkt-ID's zurückgibt, angegeben werden. Wird dies getan, werden nur die darin vorkommenden Produkt-ID's für die Analyse berücksichtigt.
  • excluding_items:
    Die Produkt-ID's dieses REF CURSOR werden bei der Analyse nicht berücksichtigt.

Eine konkrete Anwendung der Funktion in einer SQL-Abfrage sieht so aus ...

select 
  column_value,
  support,
  length,
  total_tranx
from table(
  dbms_frequent_itemset.fi_transactional(
    cursor(
      select
        cust_id || ' ' || time_id,
        prod_name
      from sh.sales join sh.products using (prod_id)
    ),
    0.05,
    2,
    2
  )
) fi, table(fi.itemset)

Der erste übergebene Parameter (hier rot markiert) ist ein mit der SQL-Funktion cursor() erzeugter REF CURSOR. Die SQL-Abfrage des Cursors liefert die Transaktions-ID, die sich aus Kunde-ID und Datum zusammensetzt, und den Namen des jeweiligen Produktes zurück. Als support_threshold wird hier 0,05 angegeben. Von Interesse sind also nur die Produktkombinationen, die in mehr als 5% der Fälle auftreten. Weiterhin wird mit dem Wert 2 sowohl für itemset_length_min als auch für itemset_length_max festgelegt, dass Kombinationen von genau zwei Produkten von Interesse sind. 

Das Ergebnis der Abfrage enthält quasi eine geschachtelte Tabelle (Abbildung 2). Dies ist nötig, da die Anzahl der Produkte in den gefundenen Kombinationen durch die Parameter itemset_length_min und itemset_length_max variabel ist. Um die Ergebnisse im SQL Workshop oder in einem Application Express-Bericht richtig anzeigen zu können, wird die TABLE()-Funktion verwendet - Sie wandelt die geschachtelte Struktur in ein flaches Ausgabeformat um.

Ergebnisstruktur der Abfrage
Abb.2: Ergebnisstruktur der Abfrage

Nun können Sie die Abfrage im SQL Workshop testen ...

Testen der Abfrage im SQL Workshop
Abb.3: Testen der Abfrage im SQL Workshop

Das geschachtelte Ergebnis wurde mit TABLE() in ein flaches Tabellenformat umgewandelt - also gehören stets zwei Zeilen zusammen. Mit diesen Erkenntnissen kann nun eine Application Express-Seite erstellt werden. Legen Sie dazu folgende Elemente an:

  • PX_ANZAHL_PRODUKTE_MIN
  • PX_ANZAHL_PRODUKTE_MAX
  • PX_SUPPORT_THRESHOLD
Auswertungsseite: Parameter
Abb.4: Auswertungsseite: Parameter

Legen Sie als nächstes den Bericht an. Verwenden Sie dafür das folgende SQL-Kommando:

select 
freq_itemlist.rangfolge,
freq_item.column_value,
freq_itemlist.support / freq_itemlist.total_tranx * 100 as support,
freq_itemlist.length,
freq_itemlist.total_tranx
from (
select
itemset,
support,
length,
total_tranx,
rank() over (order by support desc) as rangfolge
from table(
dbms_frequent_itemset.fi_transactional(
cursor(
select
cust_id || ' ' || time_id,
prod_name
from sh.sales join sh.products using (prod_id)
),
:P2_SUPPORT_THRESHOLD,
:P2_ANZAHL_PRODUKTE_MIN,
:P2_ANZAHL_PRODUKTE_MAX
)
)
) freq_itemlist, table (freq_itemlist.itemset) freq_item
order by rangfolge asc

Der hier rot markierte Bereich des SQL-Kommandos führt die eigentliche Ermittlung der am häufigsten gekauften Produktkombinationen durch. Hier ist der Aufruf von DBMS_FREQUENT_ITEMSET.FI_TRANSACTIONAL enthalten - die Application Express-Elemente P2_SUPPORT_THRESHOLD, P2_ANZAHL_PRODUKTE_MIN und P2_ANZAHL_PRODUKTE_MAX werden als Parameter übergeben. Mit der analytischen Funktion RANK ... OVER wird eine Rangfolge anhand der Häufigkeit der jeweligen Produktkombination ermittelt - nach dieser wird zum Abschluss sortiert. 

Das Ergebnis sieht nach etwas Arbeit am Layout wie folgt aus:

Das Ergebnis ... Die am häufigsten gekauften Produktkombinationen
Abb.5: Das Ergebnis ... Die am häufigsten gekauften Produktkombinationen

DBMS_FREQUENT_ITEMSET ist in allen Editionen der Oracle-Datenbank enthalten. Dieses Beispiel zeigt einmal mehr, wie einfach es ist, selbst anspruchsvolle Analyse-Anforderungen mit Application Express zu lösen. 

Weitere Informationen zum Thema:

Zurück zur Community-Seite