Sample- oder ROWNUM-Klausel

09.
Januar
2018
Veröffentlicht von: Marco Patzwahl

Sample- oder ROWNUM-Klausel, das ist hier die Frage...


Mit der SAMPLE-Klausel kann die SQL-Ergebnismenge auf 0,000001% bis 100% der ursprünglichen reduziert werden.
Oracle greift einfach zufällig in die Ergebnismenge und holt (wählt) einen gewissen Prozentsatz der Daten heraus.

In der Schule nannte man das Experiment: Ziehen mit zurücklegen :-)

Schauen wir uns ein paar Beispiele an:

SELECT count(*) FROM big
SAMPLE (0.001);

 erster Versuch  zweiter Versuch  dritter Versuch 
 Rückgabe 1295


Man sieht also, die Rückgabemenge kann durch statistische Abweichungen mal mehr - mal weniger Zeilen zurückliefern.

Mit dem SEED-Parameter kann die Ergebnismenge auf einer Speicherplatznummer gespeichert werden (hier: Position 1)

SELECT name FROM big
SAMPLE (0.0001) SEED (1);

Ergebnis:

ORD_DICOM
WWV_FLOW_PREFERENCES
DBMS_SQLTUNE

 

SELECT name FROM big
SAMPLE (0.0001) SEED (2);

Ergebnis:

DBMS_STATS


Wenn Sie die erste Ergebnismenge nochmal benötigen, setzen Sie einfach das Statement mit SEED(1) nochmal ab:

SELECT name FROM big
SAMPLE (0.0001) SEED (1);

Ergebnis:

ORD_DICOM
WWV_FLOW_PREFERENCES
DBMS_SQLTUNE


Wir konnten bei unseren Tests bis Speicheradresse SEED(4294967295) gehen. Nach dieser Speicheradresse wurden die Ergebnismengen nicht mehr geändert. Also egal welche SEED-Adresse darüber Sie verwenden, Sie bekommen immer die Daten der Nummer SEED(4294967295) zu sehen.

Sie können in das Statement auch eine WHERE-Klausel einbauen:

SELECT name FROM big sample (0.01)
WHERE name LIKE 'A%';

Aber ein Alias Name für die Tabelle ist nicht möglich:

select name from big b sample (0.01)
where name like 'A%';

SQL-Fehler: ORA-00933: SQL-Befehl wurde nicht korrekt beendet:

00933. 00000 -  "SQL command not properly ended"


Auch bei Joins geht die Sample-Klausel leider nicht:

SELECT * FROM emp,dept SAMPLE (10);


Hier endet auch leider (weg)der Nutzen der SAMPLE-Klausel, denn sobald Sie komplexere Statements haben, funktioniert die SAMPLE-Klausel nicht mehr!

Gut, dann verwenden wir wieder die altbewährte ROWNUM-Klausel. Wenn Sie verschiedene Varianten eines SQL-Statements austesten möchten und dabei feststellen, jeder Versuch dauert mehr als 3 Stunden, werden Sie diese Möglichkeit zu schätzen wissen.    

Wenn das Statement also lautet:

SELECT empno,ename,sal,loc FROM emp,dept
WHERE emp.deptno=dept.deptno;

Machen wir daraus:

SELECT * FROM
(SELECT empno,ename,sal,loc
FROM emp,dept WHERE emp.deptno=dept.deptno)
WHERE rownum<10;


Und Statements mit WITH-Klausel?

WITH t as (select deptno,loc FROM dept)
SELECT e.empno,e.ename,t.loc,t.deptno FROM t,emp e
WHERE e.deptno=t.deptno;


Ab Oracle 12.2:

SELECT * FROM (
WITH t as (SELECT deptno,loc FROM dept)
SELECT e.empno,e.ename,t.loc,t.deptno FROM t,emp e
WHERE t.deptno=e.deptno)
WHERE rownum<10;


Oder alternativ:

WITH t as (select deptno,loc FROM dept)
SELECT * FROM (   -- ### Hier wurde die Zusatzklausel eingefügt
SELECT e.empno,e.ename,t.loc,t.deptno FROM t,emp e
WHERE t.deptno=e.deptno)
WHERE rownum<10; -- ### Hier endet die Zusatzklausel


Wenn die Ergebnismenge sehr groß ist, kann man auch nur einen COUNT(*) verwenden.

Dieser muss auch die ganze Ergebnismenge durchgehen, sich aber nicht mit der (lästigen und langwierigen) Zeilenausgabe beschäftigen:

SELECT count(*) FROM (
WITH t as (SELECT deptno,loc FROM dept)
SELECT e.empno,e.ename,t.loc,t.deptno FROM t,emp e
WHERE t.deptno=e.deptno)
WHERE rownum<10;


Weitere Öffnet internen Link im aktuellen FensterTipps & Tricks bekommenn Sie in unseren Öffnet internen Link im aktuellen FensterTuning-Kursen. Besuchen Sie und doch einfach mal :-) 

Jede Menge Know-how für Sie!

In unserer Know-How Datenbank finden Sie mehr als 300 ausführliche Beiträge zu den Oracle-Themen wie DBA, SQL, PL/SQL, APEX und vielem mehr.
Hier erhalten Sie Antworten auf Ihre Fragen.