Dieses Kapitel beschreibt, wie die Ausführung eines Statements von einem Gruppenwechsel abhängig gemacht werden kann, und wie Gruppenwechsel für die Auswertung von Natural-Systemfunktionen benutzt werden können.
Folgende Themen werden behandelt:
Ein Gruppenwechsel (Break) findet statt, wenn der Wert eines Kontrollfeldes sich ändert.
Die Ausführung von Statements kann von einem solchen Gruppenwechsel abhängig gemacht werden.
Ein Gruppenwechsel kann auch zur Auswertung von Natural-Systemfunktionen verwendet werden.
Systemfunktionen werden im Abschnitt Systemvariablen und Systemfunktionen behandelt. Genauere Beschreibungen der verfügbaren Systemfunktionen finden Sie in der Systemfunktionen-Dokumentation.
Mit dem Statement AT BREAK
können Sie eine Verarbeitung angeben, die immer dann ausgeführt werden soll, wenn ein
Gruppenwechsel erfolgt, d.h. wenn der Wert eines Kontrollfeldes, das Sie im AT
BREAK-Statement angeben, sich ändert. Als Kontrollfeld können Sie ein
Datenbankfeld oder eine Benutzervariable verwenden.
In diesem Abschnitt werden folgende Themen behandelt:
Das Feld, welches als Kontrollfeld in einem AT
BREAK-Statement angegeben wird, ist üblicherweise ein
Datenbankfeld.
Beispiel:
... AT BREAK OF DEPT statements END-BREAK ...
In diesem Beispiel ist das Datenbankfeld DEPT das Kontrollfeld; wechselt
der Wert des Feldes, beispielsweise von SALE01 auf SALE02,
würde dies die Ausführung der im AT BREAK-Statement angegebenen
Statements auslösen.
Es ist auch möglich, statt eines ganzen Feldes nur einen Teil eines Feldes als
Kontrollfeld zu nehmen. Mit der Notation /n/ können Sie festlegen, dass nur
die ersten /n/ Stellen eines Feldes auf einen
Wertwechsel überprüft werden sollen.
Beispiel:
... AT BREAK OF DEPT /4/ statements END-BREAK ...
In diesem Beispiel würden die angegebenen Statements nur ausgeführt, wenn sich
der Wert der ersten 4 Stellen des Feldes DEPT ändern würde, beispielsweise
von SALE auf TECH; ein Wechsel von SALE01 auf
SALE02 hingegen würde ignoriert und der AT BREAK-Block nicht
ausgeführt werden.
** Example 'ATBREX01': AT BREAK OF (with database field)
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
2 NAME
2 CITY
2 COUNTRY
2 JOB-TITLE
2 SALARY (1:1)
END-DEFINE
*
READ (5) MYVIEW BY CITY WHERE COUNTRY = 'USA'
DISPLAY CITY (AL=9) NAME 'POSITION' JOB-TITLE 'SALARY' SALARY(1)
/*
AT BREAK OF CITY
WRITE / OLD(CITY) (EM=X^X^X^X^X^X^X^X^X^X^X^)
5X 'AVERAGE:' T*SALARY AVER(SALARY(1)) //
COUNT(SALARY(1)) 'RECORDS FOUND' /
END-BREAK
/*
AT END OF DATA
WRITE 'TOTAL (ALL RECORDS):' T*SALARY(1) TOTAL(SALARY(1))
END-ENDDATA
END-READ
END
Im obigen Programm wird das erste WRITE-Statement ausgeführt, wenn der Wert des Feldes
CITY sich ändert.
Im AT BREAK-Statement werden die Systemfunktionen OLD, AVER und COUNT ausgewertet (und in dem
WRITE-Statement ausgegeben).
In dem AT END OF
DATA-Statement wird die Systemfunktion TOTAL ausgewertet.
Das Programm ATBREX01 erzeugt folgende Ausgabe:
Page 1 04-12-14 14:07:26
CITY NAME POSITION SALARY
--------- -------------------- ------------------------- ----------
AIKEN SENKO PROGRAMMER 31500
A I K E N AVERAGE: 31500
1 RECORDS FOUND
ALBUQUERQ HAMMOND SECRETARY 22000
ALBUQUERQ ROLLING MANAGER 34000
ALBUQUERQ FREEMAN MANAGER 34000
ALBUQUERQ LINCOLN ANALYST 41000
A L B U Q U E R Q U E AVERAGE: 32750
4 RECORDS FOUND
TOTAL (ALL RECORDS): 162500
Auch eine Benutzervariable kann als
Kontrollfeld in einem AT
BREAK-Statement verwendet werden.
Im folgenden Programm wird die Benutzervariable #LOCATION als Kontrollfeld
verwendet.
** Example 'ATBREX02': AT BREAK OF (with user-defined variable and
** in conjunction with BEFORE BREAK PROCESSING)
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
2 CITY
2 COUNTRY
2 JOB-TITLE
2 SALARY (1:1)
*
1 #LOCATION (A20)
END-DEFINE
*
READ (5) MYVIEW BY CITY WHERE COUNTRY = 'USA'
BEFORE BREAK PROCESSING
COMPRESS CITY 'USA' INTO #LOCATION
END-BEFORE
DISPLAY #LOCATION 'POSITION' JOB-TITLE 'SALARY' SALARY (1)
/*
AT BREAK OF #LOCATION
SKIP 1
END-BREAK
END-READ
END
Ausgabe des Programms ATBREX02:
Page 1 04-12-14 14:08:36
#LOCATION POSITION SALARY
-------------------- ------------------------- ----------
AIKEN USA PROGRAMMER 31500
ALBUQUERQUE USA SECRETARY 22000
ALBUQUERQUE USA MANAGER 34000
ALBUQUERQUE USA MANAGER 34000
ALBUQUERQUE USA ANALYST 41000
Mit der Notation /n/ können Sie, wie oben erläutert, den Teil
eines Feldes zum Kontrollfeld eines Gruppenwechsels machen. Sie können auch mehrere
AT BREAK-Statements
miteinander kombinieren, wobei bei einem Gruppenwechsel ein ganzes Feld und bei einem
anderen ein Teil dieses Feldes Kontrollfeld ist.
In diesem Fall muss der übergeordnete Gruppenwechsel (ganzes Feld) vor dem
untergeordneten (Teil des Feldes) angegeben werden, d.h. im ersten AT
BREAK-Statement muss das ganze Feld, im zweiten das Teilfeld als Kontrollfeld
angegeben werden.
Das folgende Beispielprogramm zeigt dies anhand des Feldes DEPT und den
ersten 4 Stellen dieses Feldes (DEPT /4/).
** Example 'ATBREX03': AT BREAK OF (two statements in combination)
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
2 NAME
2 JOB-TITLE
2 DEPT
2 SALARY (1:1)
2 CURR-CODE (1:1)
END-DEFINE
*
READ MYVIEW BY DEPT STARTING FROM 'SALE40' ENDING AT 'TECH10'
WHERE SALARY(1) GT 47000 AND CURR-CODE(1) = 'USD'
/*
AT BREAK OF DEPT
WRITE '*** LOWEST BREAK LEVEL ***' /
END-BREAK
AT BREAK OF DEPT /4/
WRITE '*** HIGHEST BREAK LEVEL ***'
END-BREAK
/*
DISPLAY DEPT NAME 'POSITION' JOB-TITLE
END-READ
END
Ausgabe des Programms ATBREX03:
Page 1 04-12-14 14:09:20
DEPARTMENT NAME POSITION
CODE
---------- -------------------- -------------------------
TECH05 HERZOG MANAGER
TECH05 LAWLER MANAGER
TECH05 MEYER MANAGER
*** LOWEST BREAK LEVEL ***
TECH10 DEKKER DBA
*** LOWEST BREAK LEVEL ***
*** HIGHEST BREAK LEVEL ***
Im folgenden Programm wird jedesmal, wenn sich der Wert des Feldes DEPT
ändert, eine Leerzeile ausgegeben; und jedesmal, wenn sich der Wert in den ersten 4
Stellen von DEPT ändert, wird über die Systemfunktion COUNT die Anzahl der
verarbeiteten Datensätze ermittelt.
** Example 'ATBREX04': AT BREAK OF (two statements in combination)
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
2 DEPT
2 REDEFINE DEPT
3 #GENDEP (A4)
2 NAME
2 SALARY (1)
END-DEFINE
*
WRITE TITLE '** PERSONS WITH SALARY > 30000, SORTED BY DEPARTMENT **' /
LIMIT 9
READ MYVIEW BY DEPT FROM 'A' WHERE SALARY(1) > 30000
DISPLAY 'DEPT' DEPT NAME 'SALARY' SALARY(1)
/*
AT BREAK OF DEPT
SKIP 1
END-BREAK
AT BREAK OF DEPT /4/
WRITE COUNT(SALARY(1)) 'RECORDS FOUND IN:' OLD(#GENDEP) /
END-BREAK
END-READ
END
Ausgabe des Programms ATBREX04:
** PERSONS WITH SALARY > 30000, SORTED BY DEPARTMENT **
DEPT NAME SALARY
------ -------------------- ----------
ADMA01 JENSEN 180000
ADMA01 PETERSEN 105000
ADMA01 MORTENSEN 320000
ADMA01 MADSEN 149000
ADMA01 BUHL 642000
ADMA02 HERMANSEN 391500
ADMA02 PLOUG 162900
ADMA02 HANSEN 234000
8 RECORDS FOUND IN: ADMA
COMP01 HEURTEBISE 168800
1 RECORDS FOUND IN: COMP
Automatische Gruppenwechsel-Verarbeitung ist für eine Verarbeitungsschleife aktiv, die
ein AT BREAK-Statement enthält.
Dies gilt für die folgenden Statements:
Hierbei wird der Wert des im AT
BREAK-Statement angegebenen Kontrollfeldes nur bei den Datensätzen
überprüft, die die WITH- und WHERE-Auswahlkriterien der Verarbeitungsschleife
erfüllen.
Natural-Systemfunktionen (AVER, MAX, MIN usw.) werden
für jeden Datensatz ausgewertet, nachdem alle in der Verarbeitungsschleife enthaltenen
Statements ausgeführt worden sind. Datensätze, die aufgrund des WHERE-Kriteriums nicht
verarbeitet werden, werden bei der Auswertung der Systemfunktionen nicht berücksichtigt.
Die Abbildung auf der folgenden Seite veranschaulicht den Verarbeitungsablauf eines automatischen Gruppenwechsels.

Das folgende Beispiel zeigt die Verwendung der Natural-Systemfunktionen
OLD, MIN, AVER, MAX, SUM und COUNT in einem AT BREAK-Statement (und der
Systemfunktion TOTAL in
einem AT END OF
DATA-Statement).
** Example 'ATBREX05': AT BREAK OF (with system functions)
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
2 NAME
2 CITY
2 SALARY (1:1)
2 CURR-CODE (1:1)
END-DEFINE
*
LIMIT 3
READ MYVIEW BY CITY = 'SALT LAKE CITY'
DISPLAY NOTITLE CITY NAME 'SALARY' SALARY(1) 'CURRENCY' CURR-CODE(1)
/*
AT BREAK OF CITY
WRITE / OLD(CITY) (EM=X^X^X^X^X^X^X^X^X^X^X^X^X^X^X)
31T ' - MINIMUM:' MIN(SALARY(1)) CURR-CODE(1) /
31T ' - AVERAGE:' AVER(SALARY(1)) CURR-CODE(1) /
31T ' - MAXIMUM:' MAX(SALARY(1)) CURR-CODE(1) /
31T ' - SUM:' SUM(SALARY(1)) CURR-CODE(1) /
33T COUNT(SALARY(1)) 'RECORDS FOUND' /
END-BREAK
/*
AT END OF DATA
WRITE 22T 'TOTAL (ALL RECORDS):'
T*SALARY TOTAL(SALARY(1)) CURR-CODE(1)
END-ENDDATA
END-READ
END
Ausgabe des Programms ATBREX05:
CITY NAME SALARY CURRENCY
-------------------- -------------------- ---------- --------
SALT LAKE CITY ANDERSON 50000 USD
SALT LAKE CITY SAMUELSON 24000 USD
S A L T L A K E C I T Y - MINIMUM: 24000 USD
- AVERAGE: 37000 USD
- MAXIMUM: 50000 USD
- SUM: 74000 USD
2 RECORDS FOUND
SAN DIEGO GEE 60000 USD
S A N D I E G O - MINIMUM: 60000 USD
- AVERAGE: 60000 USD
- MAXIMUM: 60000 USD
- SUM: 60000 USD
1 RECORDS FOUND
TOTAL (ALL RECORDS): 134000 USD
Siehe folgendes Beispielprogramm:
ATBREX06 - AT BREAK OF-Statement (zum Vergleichen von NMIN, NAVER, NCOUNT mit MIN, AVER, COUNT)
Mit dem Statement BEFORE BREAK
PROCESSING können Sie Statements angeben, die unmittelbar vor einem
Gruppenwechsel ausgeführt werden sollen, d.h. bevor der Wert des Kontrollfeldes geprüft
wird, bevor die Statements im AT
BREAK-Block ausgeführt werden und bevor Natural-Systemfunktionen ausgewertet werden.
** Example 'BEFORX01': BEFORE BREAK PROCESSING
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
2 NAME
2 FIRST-NAME
2 SALARY (1:1)
2 BONUS (1:1,1:1)
*
1 #INCOME (P11)
END-DEFINE
*
LIMIT 5
READ MYVIEW BY NAME FROM 'B'
BEFORE BREAK PROCESSING
COMPUTE #INCOME = SALARY(1) + BONUS(1,1)
END-BEFORE
/*
DISPLAY NOTITLE NAME FIRST-NAME (AL=10)
'ANNUAL/INCOME' #INCOME 'SALARY' SALARY(1) (LC==) /
'+ BONUS' BONUS(1,1) (IC=+)
AT BREAK OF #INCOME
WRITE T*#INCOME '-'(24)
END-BREAK
END-READ
END
Ausgabe des Programms BEFORX01:
NAME FIRST-NAME ANNUAL SALARY
INCOME + BONUS
-------------------- ---------- ------------ -----------
BACHMANN HANS 56800 = 52800
+4000
------------------------
BAECKER JOHANNES 81000 = 74400
+6600
------------------------
BAECKER KARL 52650 = 48600
+4050
------------------------
BAGAZJA MARJAN 152700 = 129700
+23000
------------------------
BAILLET PATRICK 198500 = 188000
+10500
------------------------
Bei automatischer Gruppenwechsel-Verarbeitung werden die im AT BREAK-Block angegebenen
Statements jedesmal ausgeführt, wenn sich der Wert des angegebenen Kontrollfeldes ändert,
und zwar unabhängig von der Position des AT
BREAK-Statements in der Verarbeitungsschleife.
Mit einem PERFORM BREAK
PROCESSING-Statement können Sie selbst festlegen, wo in einer
Verarbeitungsschleife eine Gruppenwechsel-Verarbeitung ausgeführt werden soll. Das
PERFORM BREAK PROCESSING-Statement wird dann ausgeführt, wenn es im
Verarbeitungsablauf des Programms angetroffen wird.
Unmittelbar nach dem PERFORM BREAK PROCESSING-Statement geben Sie einen oder
mehrere AT BREAK-Statement-Blöcke an:
...
PERFORM BREAK PROCESSING
AT BREAK OF field1
statements
END-BREAK
AT BREAK OF field2
statements
END-BREAK
...
Wenn ein PERFORM BREAK PROCESSING-Statement ausgeführt wird, prüft Natural,
ob ein Gruppenwechsel stattgefunden hat, d.h. ob der Wert des angegebenen Kontrollfeldes
sich geändert hat; ist dies der Fall, dann werden die angegebenen Statements
ausgeführt.
Bei PERFORM BREAK PROCESSING werden Systemfunktionen ausgewertet,
bevor Natural prüft, ob ein Gruppenwechsel stattgefunden hat.
Die folgende Abbildung zeigt den logischen Ablauf einer programmabhängigen Gruppenwechsel-Verarbeitung:

** Example 'PERFBX01': PERFORM BREAK PROCESSING (with BREAK option
** in IF statement)
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
2 NAME
2 DEPT
2 SALARY (1:1)
*
1 #CNTL (N2)
END-DEFINE
*
LIMIT 7
READ MYVIEW BY DEPT
AT BREAK OF DEPT /* <- automatic break processing
SKIP 1
WRITE 'SUMMARY FOR ALL SALARIES '
'SUM:' SUM(SALARY(1))
'TOTAL:' TOTAL(SALARY(1))
ADD 1 TO #CNTL
END-BREAK
/*
IF SALARY (1) GREATER THAN 100000 OR BREAK #CNTL
PERFORM BREAK PROCESSING /* <- user-initiated break processing
AT BREAK OF #CNTL
WRITE 'SUMMARY FOR SALARY GREATER 100000'
'SUM:' SUM(SALARY(1))
'TOTAL:' TOTAL(SALARY(1))
END-BREAK
END-IF
/*
IF SALARY (1) GREATER THAN 150000 OR BREAK #CNTL
PERFORM BREAK PROCESSING /* <- user-initiated break processing
AT BREAK OF #CNTL
WRITE 'SUMMARY FOR SALARY GREATER 150000'
'SUM:' SUM(SALARY(1))
'TOTAL:' TOTAL(SALARY(1))
END-BREAK
END-IF
DISPLAY NAME DEPT SALARY(1)
END-READ
END
Ausgabe des Programms PERFBX01:
Page 1 04-12-14 14:13:35
NAME DEPARTMENT ANNUAL
CODE SALARY
-------------------- ---------- ----------
JENSEN ADMA01 180000
PETERSEN ADMA01 105000
MORTENSEN ADMA01 320000
MADSEN ADMA01 149000
BUHL ADMA01 642000
SUMMARY FOR ALL SALARIES SUM: 1396000 TOTAL: 1396000
SUMMARY FOR SALARY GREATER 100000 SUM: 1396000 TOTAL: 1396000
SUMMARY FOR SALARY GREATER 150000 SUM: 1142000 TOTAL: 1142000
HERMANSEN ADMA02 391500
PLOUG ADMA02 162900
SUMMARY FOR ALL SALARIES SUM: 554400 TOTAL: 1950400
SUMMARY FOR SALARY GREATER 100000 SUM: 554400 TOTAL: 1950400
SUMMARY FOR SALARY GREATER 150000 SUM: 554400 TOTAL: 1696400