Funktionsbaustein implementieren


Getting started ... Alles für einen gelungenen Start.

Moderatoren: Jan, Steff

Funktionsbaustein implementieren

Beitragvon Gerrit » 06.03.2018, 19:47

Hallo ABAP-Gemeinschaft, ich habe die Aufgabe einen Funktionsbaustein zu schreiben, dieser soll folgenden Zweck erfüllen:


Es soll geprüft werden, ob sowohl für die Hinflugverbindung als auch für die
Rückflugverbindung noch Einzelflüge existieren, für die es freie Plätze gibt. Beachten Sie
dabei unbedingt folgende Hinweise:
 Die Einzelflüge stehen in der Tabelle SFLIGHT.
 Für jede Flugverbindung gibt es in der Regel mehrere Einzelflüge. Sie müssen nicht
nur prüfen ob es solche Einzelflüge gibt, sondern schauen ob einer dieser Flüge noch
freie Plätze hat. Ein häufiger Fehler ist, nur einen Hinflug und einen Rückflug aus der
Datenbank zu lesen und zu prüfen ob diese beide freie Plätze haben, obwohl ja wie
erwähnt mehrere Einzelflüge für den Hinflug zur Auswahl stehen und mehrere
Einzelflüge für den Rückflug zur Auswahl stehen.
 Sie müssen zur Vereinfachung der Aufgabe keinerlei Datumsinformationen beachten.
 Beachten Sie, dass sie für die Bestimmung der freien Plätze in die SEATSOCC,
SEATSOCC_B-, SEATSOCC_F- sowie SEATSMAX-, SEATSMAX_B- und
SEATSMAX_F-Spalte schauen müssen. Es ist aber egal in welcher Klasse es die
freien Plätze gibt.
 Das Ergebnis (der Wert des Parameters VERFUEGBAR) soll nur dann 1 sein, wenn
sowohl für den Hinflug mindestens ein Einzelflug mit freien Plätzen existiert, als
auch für den Rückflug.


Darüber hinaus habe ich folgende Hinweise:

Es ist richtig, dass ein verfügbarer Flug für den Hinflug und ein
verfügbarer Flug für den Rückflug genügt. Wenn es sich
nun um einen Flug ohne freie Plätze handelt, würdest du nicht mehr nach
weiteren Flügen mit evtl. freien Plätzen suchen.
Um das zu beheben gibt es viele Möglichkeiten, zum Beispiel könntest du
eine SELECT-Schleife benutzen und in der Schleife die freien Plätze
ermitteln. Du musst dann nur aufpassen, dass du in der Schleife die
freien Plätze nicht jedes mal komplett überschreibst, so dass ein
später gefundener nicht-verfügbarer Flug die information über einen
zuvor gefundenen freien Flug überschreiben würde.

Du müsstest die Bedingung im WHERE-Teil auf
Basis der ursprünglichen Spalten formulieren oder das in ABAP außerhalb
des SELECT-Befehls prüfen.


Probleme habe ich vorallem mit der richtigen Implementierung der Berechnung im SELECT - Statement
seatsmax + seatsmax_b + seatsmax_f - seatsocc - seatsocc_b - seatsocc_f > 0

bzw. ob mein Ansatz/ Idee zur Lösung der Aufgabe soweit richtig ist (etwaige Fehler noch vorhanden sind)


Vielen Dank für die Hilfe und LG

Gerrit




FUNCTION Z_0000_SAufgabe.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*" IMPORTING
*" REFERENCE(CARRID1) TYPE SPFLI-CARRID
*" REFERENCE(CONNID1) TYPE SPFLI-CONNID
*" REFERENCE(CARRID2) TYPE SPFLI-CARRID
*" REFERENCE(CONNID2) TYPE SPFLI-CONNID
*" EXPORTING
*" REFERENCE(VERFUEGBAR) TYPE INTEGER4
*"----------------------------------------------------------------------


"Hinflug
"CARRID1 Kurzbezeichnung der Fluggesellschaft
"CONNID1 Code der Einzelflugverbindung

"Rückflug
"CARRID2 Kurzbezeichnung der Fluggesellschaft
"CONNID2 Code der Einzelflugverbindung

"SEATSMAX Maximale Anzahl belegbarer Sitze in der Economy Class
"SEATSOCC Belegte Plätze in der Economy Class
"SEATSMAX_B Maximale Anzahl belegbarer Sitze in der Business Class
"SEATSOCC_B Belegte Plätze in der Business Class
"SEATSMAX_F Maximale Anzahl belegbarer Sitze in der First Class
"SEATSOCC_F Belegte Plätze in der First Class



SELECT SINGLE *
FROM SFLIGHT
INTO wa_hinflug
WHERE connid = connid1 AND carrid = carrid1
AND seatsmax + seatsmax_b + seatsmax_f - seatsocc - seatsocc_b - seatsocc_f > 0.



IF sy-subrc = 0.
verfuegbar = 0.

ENDIF.




SELECT SINGLE *
FROM SFLIGHT
INTO wa_rueckflug
WHERE connid = connid2 AND carrid = carrid2
AND seatsmax + seatsmax_b + seatsmax_f - seatsocc - seatsocc_b - seatsocc_f > 0.



IF sy-subrc = 0
AND verfuegbar = 0.

verfuegbar = 1.

ENDIF.



ENDFUNCTION.
Gerrit
ForumUser
 
Beiträge: 1
Registriert: 06.03.2018, 16:47
Dank erhalten: 0 mal
Ich bin: Student/in

Sponsor

Alte ABAP-Entwicklerweisheit: Weißt du weder aus noch ein, baust du einen BADI ein

Re: Funktionsbaustein implementieren

Beitragvon schick » 08.03.2018, 08:10

Hi,

grundsätzlich gibt es x verschiedene Möglichkeiten die Aufgabe zu bewältigen.
Anbei eine auf die Schnelle runtergetippte Option.
Mit Sicherheit ist das nicht die eleganteste Möglichkeit, sollte aber den Zweck erfüllen.

Code: Alles auswählen
DATA:
  hinflug   TYPE TABLE OF sflight,
  rueckflug TYPE TABLE OF sflight.

FIELD-SYMBOLS:
  <hinflug>   TYPE sflight,
  <rueckflug> TYPE sflight.

* Alle potentiellen Hinflüge von der DB lesen
SELECT *
  FROM SFLIGHT
  INTO TABLE hinflug
  WHERE connid EQ connid1
    AND carrid EQ carrid1.

WRITE: / 'Freie Hinflüge suchen:'.

* Loop über die Hinflüge
LOOP AT hinflug ASSIGNING <hinflug>.

* Abfrage ob freie Plätze vohanden sind
  IF <hinflug>-seatsmax + <hinflug>-seatsmax_b + <hinflug>-seatsmax_f - <hinflug>-seatsocc - <hinflug>-seatsocc_b - <hinflug>-seatsocc_f GT 0.

    WRITE: / 'Hinflug gefunden.', <hinflug>-fldate.

* Mögliche Rückflüge von der DB lesen
    SELECT *
      FROM SFLIGHT
      INTO TABLE rueckflug
      WHERE connid EQ connid2
        AND carrid EQ carrid2
        AND fldate GT <hinflug>-fldate.

    WRITE: / 'Freie Rückflüge suchen:'.

* Loop über Rückflüge
    LOOP AT rueckflug ASSIGNING <rueckflug>.

* Abfrage ob freie Plätze vorhanden sind
        IF <rueckflug>-seatsmax + <rueckflug>-seatsmax_b + <rueckflug>-seatsmax_f - <rueckflug>-seatsocc - <rueckflug>-seatsocc_b - <rueckflug>-seatsocc_f GT 0.

           verfuegbar = 1.
           WRITE: / 'Rückflug gefunden.', <rueckflug>-fldate.
           EXIT.

        ENDIF.
    ENDLOOP.
    IF verfuegbar EQ 1.
      EXIT.
    ENDIF.
  ENDIF.
ENDLOOP.

 
schick
ForumUser
 
Beiträge: 17
Registriert: 16.02.2018, 08:22
Dank erhalten: 2 mal
Ich bin: Berater/in

Re: Funktionsbaustein implementieren

Beitragvon DeathAndPain » 08.03.2018, 11:32

Ich bin nicht sicher, ob es ihm was bringt, ihm einfach eine andere Lösung hinzuklatschen. Ich finde gut, dass er seine eigene Lösung gepostet hat und zur Diskussion freigibt. So kann er auch was daraus lernen.

@Gerrit:

Zunächst einmal fehlen mir die DATA-Deklarationen der verwendeten Hilfsvariablen. Wahrscheinlich stehen die im TOP-Include der Funktionsgruppe, denn da Du keine FORM verwendet hast, sind alle von Dir verwendeten Variablen zwangsläufig global. Außerdem ist nicht klar, welche Schnittstelle der Funktionsbaustein haben soll. Waren die von Dir gewählten Parameter vorgegeben? Das würde bedeuten, dass man nicht nur sucht, ob es Flüge von A nach B gibt, sondern auch die Flugnummer vorgibt. Damit kann es pro Tag aber nur (maximal) einen Flug geben (was auch der Primärschlüssel der Tabelle SFLIGHT unterstreicht).

Die Frage bestünde dann darin, ob es überhaupt einen nicht ausgebuchten Flug dieser Fluggesellschaft und mit dieser Flugnummer gibt, egal an welchem Datum. Eine ungewöhnliche Anfrage, aber nun ja.

Ein Fehler besteht zunächst mal in Deiner Auswertung des ersten SELECT. Da sagst Du nämlich:

Code: Alles auswählen
IF sy-subrc = 0.
verfuegbar = 0.

ENDIF.

Und was machst Du, wenn sy-subrc <> 0 ist? Dann wird verfuegbar nicht verändert, wird also in aller Regel auch 0 sein. Dein IF tut also gar nichts.

Ich denke, Du musst hier verfuegbar = 1 schreiben, um Dir zu merken, dass es einen Hinflug gibt. Wenn es dann keinen Rückflug gibt, kannst Du verfuegbar ja wieder auf 0 setzen.

Außerdem bedeutet das Aufsummieren von Tabellenspalten, wie Du es in Deinem SELECT machst, dass Du eine ziemlich neue SQL-Syntax verwendest, die in älteren Releases nicht erlaubt ist. Wenn Du das aber machst, dann musst Du vor alle lokalen Felder, die im SELECT auftreten, ein @ schreiben, und der INTO-Block muss, so hässlich es auch aussehen mag, ganz ans Ende, noch hinter den WHERE-Block!

Ansonsten würde ich aber sagen, dass Dein Ansatz richtig und durchaus pfiffig ist. Sicherheitshalber würde ich aber an den Anfang des Funktionsbausteins noch ein "CLEAR verfuegbar" schreiben. Deine Funktionsbausteinvariablen sind alle global und behalten ihre Werte daher auch, wenn Du den Baustein für eine andere Verbindung ein zweites Mal aufrufst. Ich bin nicht sicher (und zu faul nachzuprüfen), ob das auch für EXPORTING-Parameter gilt, möchte das aber nicht ausschließen.

Ansonsten ist natürlich ein SELECT *, mit dem Du alle Spalten liest, obgleich Du nicht eine davon brauchst, performancemäßig schlecht. Entweder Du definierst Dir ein Hilfsfeld WA_MANDT und machst dann einen SELECT MANDT, um nur eine kurze Spalte zu lesen und zugleich anzuzeigen, dass Dich der Inhalt eigentlich gar nicht interessiert, oder Du machst einen SELECT COUNT( * ). Dann brauchst Du auch keinen INTO-Block anzugeben und kannst Dir die Workarea-Variable komplett sparen.
DeathAndPain
Expert
 
Beiträge: 606
Registriert: 05.05.2006, 10:14
Dank erhalten: 146 mal
Ich bin: Entwickler/in

Re: Funktionsbaustein implementieren

Beitragvon black_adept » 08.03.2018, 14:23

Ich weiß ja nicht wie die Felder seatsmax und seatsocc gefüllt sind. Aber wenn es -wie im RL- möglich ist, dass seatsocc größer als das zugehörige seatsmax ist, dann stimmt die Abfrage
Code: Alles auswählen
WHERE ...
AND seatsmax + seatsmax_b + seatsmax_f - seatsocc - seatsocc_b - seatsocc_f > 0.
nicht sondern es muss dann pro Kategorie geprüft werden.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 2957
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 488 mal
Ich bin: Freiberufler/in

Re: Funktionsbaustein implementieren

Beitragvon schick » 08.03.2018, 16:42

DeathAndPain hat geschrieben:Ich bin nicht sicher, ob es ihm was bringt, ihm einfach eine andere Lösung hinzuklatschen. Ich finde gut, dass er seine eigene Lösung gepostet hat und zur Diskussion freigibt. So kann er auch was daraus lernen.


Ok, da muss ich dir Recht geben, ich versuche es mir zu merken.

Mir war nicht bewusst, dass ein solcher Select möglich ist, in meinem System ist ein Statement wie

Code: Alles auswählen
SELECT *
  FROM sflight
  WHERE connid EQ connid1
    AND carrid EQ carrid1
    AND seatsmax + seatsmax_b + seatsmax_f - seatsocc - seatsocc_b - seatsocc_f > 0
  INTO TABLE hinflug.


jedenfalls nicht möglich, daher kam ich mit dem Loop um die Ecke.
Das meine Lösung sicherlich nicht die eleganteste ist habe ich ja bereits eingeräumt.

Den funktionierenden Select würde ich aber gern sehen wenn er fertig ist, dann kann ich hier auch noch was lernen.
schick
ForumUser
 
Beiträge: 17
Registriert: 16.02.2018, 08:22
Dank erhalten: 2 mal
Ich bin: Berater/in

Re: Funktionsbaustein implementieren

Beitragvon DeathAndPain » 09.03.2018, 12:53

Der SELECT

Code: Alles auswählen
SELECT SINGLE *
FROM SFLIGHT
WHERE connid = @connid1 AND carrid = @carrid1
AND seatsmax + seatsmax_b + seatsmax_f - seatsocc - seatsocc_b - seatsocc_f > 0 INTO @wa_hinflug.


wird zumindest in meinem System (7.50) nicht angemeckert. Er verlangt dann aber unter Verweis auf neue Syntax das Escaping von Hostvariablen mit dem @-Symbol (wie oben dargestellt), und er verlangt dann auch, dass der INTO ganz am Schluss steht (gleichfalls wie oben dargestellt).

Eröffnet natürlich ganz nette Optionen, weil man auf diese Weise offenbar so einiges direkt in der Datenbank ausführen lassen kann, was die Ausführungszeit optimieren dürfte.
DeathAndPain
Expert
 
Beiträge: 606
Registriert: 05.05.2006, 10:14
Dank erhalten: 146 mal
Ich bin: Entwickler/in

Re: Funktionsbaustein implementieren

Beitragvon schick » 09.03.2018, 13:47

DeathAndPain hat geschrieben:Der SELECT

Code: Alles auswählen
SELECT SINGLE *
FROM SFLIGHT
WHERE connid = @connid1 AND carrid = @carrid1
AND seatsmax + seatsmax_b + seatsmax_f - seatsocc - seatsocc_b - seatsocc_f > 0 INTO @wa_hinflug.


wird zumindest in meinem System (7.50) nicht angemeckert. Er verlangt dann aber unter Verweis auf neue Syntax das Escaping von Hostvariablen mit dem @-Symbol (wie oben dargestellt), und er verlangt dann auch, dass der INTO ganz am Schluss steht (gleichfalls wie oben dargestellt).

Eröffnet natürlich ganz nette Optionen, weil man auf diese Weise offenbar so einiges direkt in der Datenbank ausführen lassen kann, was die Ausführungszeit optimieren dürfte.


Ok, dann ist mein 7.4-System wohl einfach zu alt...
Ich bekomme einen Fehler:

"+" ist grammatikalisch hier nicht erlaubt. Schlüsselwort ist. Ggf. ist
es durch "!" zu maskieren. Oder es fehlt ein Leerzeichen oder es ist
eines zuviel.
schick
ForumUser
 
Beiträge: 17
Registriert: 16.02.2018, 08:22
Dank erhalten: 2 mal
Ich bin: Berater/in

Re: Funktionsbaustein implementieren

Beitragvon DeathAndPain » 09.03.2018, 14:23

Ja, mit 7.40 kamen die ganzen schönen neuen ABAP-Befehle, aber ich denke, diese SQL-Erweiterungen kamen mit 7.50.
DeathAndPain
Expert
 
Beiträge: 606
Registriert: 05.05.2006, 10:14
Dank erhalten: 146 mal
Ich bin: Entwickler/in


Zurück zu ABAP® für Anfänger

  Aktuelle Beiträge   
Ausgangszeugnis
Gestern von HH_ABAP 2 Antw.
Editierbarer ALV - Zeilen einfügen verbieten
Gestern von ewx 3 Antw.
gelöst Dynamic Cast von Superclass auf Subclass
Gestern von AdrianSchm 2 Antw.
gelöst PLMKB: Spalte "Untere Grenze"
Gestern von DeathAndPain 1 Antw.
PDF Formular
vor 3 Stunden von ralf.wenzel 2 Antw.

  Ähnliche Beiträge beta
PasswortReset funktional über ODataService implementieren
10.08.2017, 15:33 von ABAP_Newbie1993 2 Antw.

 

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder