Announcement

Collapse
No announcement yet.

Errechnung eines Summenproduktes

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Errechnung eines Summenproduktes

    Hallo,
    ich muß anhand einer Tabelle <B>personal</B> und der Tabelle <B>Lohnarten</B> einen kumulierten Wert aus mehreren Lohnartenpreisen errechnen.
    Vereinfachter Aufbau der Tabellen:<P>
    <B>PERSONAL</B><P>
    <B>personalnr, name</B><BR>
    100001, meyer<BR>
    100002, schulze<P>
    <B>LOHNARTEN</B><P>
    <B>personalnr, lohnartnr, preis</B><BR>
    100001, 10, 24<BR>
    100001, 29, 17,50<BR>
    100001, 31, 12,30<BR>
    100001, 34, 22<BR>
    100002, 10, 23,50<BR>
    100002, 31, 14,20<BR>
    <P>

    Für jeden Mitarbeiter soll eine Zeile angezeigt werden, bestehend personalnr u. lohnsumme. Ich muß dazu die Summe der Lohnartenpreise 10 u. 29 durch 2 dividieren und die verbleibenden Lohnartenpreise (31 u. 34) dazuaddieren. Dieses Produkt ist dann die Lohnsumme. Als Beispiel bei Personummer 100001: 24 + 17,50 = 41,50 / 2 = 20,75. 20,75 + 12,30 + 22 = 55,05.<P>
    Und da ich seit vielen Stunden zu blöd bin, frag ich Euch, ob Ihr mir weiterhelfen könnt. Danke, Sven

  • #2
    Hi,

    Erweitere deine Tabelle LOHNARTEN um die Spalte Faktor, welche den entsprechenden Multiplikator enthält. Dann kannst Du mit folgenden Statement deine Auswertung bekommen:
    <pre>
    select personalnr, sum( preis * faktor ) from lohnarten group by personalnr;
    </pre>

    Gruß
    Gesine

    p.s:
    Da Ding in einem View verpackt kann dann mit deiner PERSONAL-Tabelle 'gejoint' werden

    Comment


    • #3
      Hi Gesine,
      erstmal: hab schon viel Gutes über Dich hier gelesen - kann man ja mal so sagen.<P> Leider kann ich die Tabellen nicht verändern, da es sich hier um eine Software für die Zeitarbeit handelt und ich außer Generierung von eben solchen Listen keine anderen Möglichkeiten habe in den Datenbanken etwas zu verändern.<P> Vielleicht hilft es Dir weiter, daß es eine Interbase4-DB ist.<P>
      Sve

      Comment


      • #4
        Hi Sven,

        Na dann hoffen wir, dass Du wenigstens einen View erzeugen darfst... ( Falls nicht, wirst Du wohl mit zwei Zeilen pro Mitarbeiter leben müssen )

        1)
        <pre>
        CREATE VIEW LOHNARTSUMMEN (
        PNR,
        SUMME
        ) AS

        select personalnr, sum( preis * 0.5 ) from lohnarten where ( lohnart=10 or lohnart=29 ) group by personalnr
        union all
        select personalnr, sum( preis * 1 ) from lohnarten where not ( lohnart=10 or lohnart=29 ) group by personalnr;
        </pre>

        2)
        auf diesen View dann ein:

        <pre>
        select pnr, sum(SUMME) from LOHNARTSUMMEN group by pnr
        </pre>

        Gruß
        Gesine

        p.s.:
        Danke für's Komplimen

        Comment


        • #5
          Hi Gesine,
          ich hab leg jetzt mal den Code der Procedure mit bei(ich greife mit SELECT drauf zu). Das Ergebnis ist zwar inzwischen soweit, daß IB nicht mehr abstürzt, ich aber zu jedem einzelnen Mitarbeiter viele Sätze angezeigt bekomme (will nur einen) und alle haben unter "Spanne" eine 0,00.<BR>Anhand zweier einzugebender Datumswerte soll ein bestimmter Schnitt aus verschiedenen Lohnarten berechnet werden. Hier der Code (lach nicht, ich fang grad an mit SQL)<P>
          (EDatum_von DATE, EDatum_bis DATE)<BR>
          RETURNS(<BR>
          Nr INTEGER,<BR>
          Name CHAR(30),<BR>
          Vorname CHAR(30),<BR>
          Spanne double precision<BR>
          )<BR>
          <BR>
          AS<BR>
          DECLARE VARIABLE XPNr INTEGER;<BR>
          DECLARE VARIABLE LART INTEGER;<BR>
          DECLARE VARIABLE LPREIS double precision;<BR>
          DECLARE VARIABLE XZwsum double precision;<BR>
          DECLARE VARIABLE XZwsum2 double precision;<BR>
          <BR>
          BEGIN<BR>
          <BR>
          FOR SELECT distinct personal.personalnr, personal.nachname, personal.vorname<BR>
          FROM personal, einspers, auftrloa<BR>
          WHERE einspers.datumvon>=:EDatum_von <BR>
          AND einspers.datumbis<=:EDatum_bis<BR>
          AND personal.personalnr=auftrloa.personalnr<BR>
          AND einspers.personalnr=auftrloa.personalnr<BR>
          AND auftrloa.auftragnr=einspers.auftragnr<BR><BR>

          INTO :XPNr, Name, Vorname DO BEGIN<BR>
          Nr = :XPNr;<BR>
          Spanne=0;<BR>
          XZwsum=0;<BR>
          XZwsum2=0;<BR>
          FOR SELECT lohnart, preis from auftrloa<BR>
          WHERE Personalnr = :XPNr<BR>
          GROUP BY lohnart, preis<BR>
          INTO LART, LPREIS DO BEGIN<BR>
          IF (LART = 10) THEN<BR>
          XZwsum2 = XZwsum2 + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 29) THEN<BR>
          XZwsum = XZwsum + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 30) THEN<BR>
          XZwsum = XZwsum + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 31) THEN<BR>
          XZwsum = XZwsum + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 32) THEN<BR>
          XZwsum = XZwsum + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 34) THEN<BR>
          XZwsum = XZwsum + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 37) THEN<BR>
          XZwsum = XZwsum + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 38) THEN<BR>
          XZwsum = XZwsum + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 39) THEN<BR>
          XZwsum = XZwsum + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 40) THEN<BR>
          XZwsum2 = XZwsum2 + LPREIS;<BR>
          suspend;<BR>
          IF (LART = 48) THEN<BR>
          XZwsum = XZwsum + LPREIS;<BR>
          suspend;<BR>
          END<BR><BR>

          XZwsum = (XZwsum / 8);<BR>
          Spanne = XZwsum + XZwsum2;<BR>
          END<BR>
          END<P>Meine SELECT-Klausel lautet:<P>
          Select Nr{Personalnr}, Name{Nachname}, Vorname{Vorname}, Spanne{Spanne}<BR>
          From Temp([3Datum_von], [3Datum_bis])<P><P>
          Ich hoffe, Du kannst damit etwas anfangen.
          Gruß Sve

          Comment


          • #6
            Hi nochmal,<P>

            nur für Dich zur Info. Ich habe meine vorher beschriebene SELECT-Klausel insoweit abgeändert, als daß ich jetzt wenigstens für jeden Mitarbeiter nur noch eine Zeile erhalte. Leider immer noch mit 0,00 in "Spanne".<P>

            Noch 'n Gruß von Sve

            Comment


            • #7
              Hallo Sven,

              ich würde entweder eine(n) View erzeugen (wie von Gesine gezeigt) + 1 StoredProc oder das Ganze auf 2 StoredProcs verteilen.

              Hier die Variante mit 2 StoredProcs:
              <pre>
              create procedure subselect_lohnarten(von_datum date, bis_datum date)
              returns
              ( nr integer,
              spanne double precision)
              as
              begin
              for select personalnr, sum( preis * 0.5 ) from lohnarten
              where ( lohnart=10 or lohnart=29 ) and
              einspers.datumvon>=:EDatum_von AND
              einspers.datumbis<=:EDatum_bis AND
              personal.personalnr=auftrloa.personalnr AND
              einspers.personalnr=auftrloa.personalnr AND
              auftrloa.auftragnr=einspers.auftragnr
              group by personalnr
              into :nr, :spanne
              do suspend;<br>

              for select personalnr, sum( preis * 1 ) from lohnarten
              where ( lohnart<>10 and lohnart<>29 ) and
              einspers.datumvon>=:EDatum_von AND
              einspers.datumbis<=:EDatum_bis AND
              personal.personalnr=auftrloa.personalnr AND
              einspers.personalnr=auftrloa.personalnr AND
              auftrloa.auftragnr=einspers.auftragnr
              group by personalnr
              into :nr, :spanne
              do suspend;
              end
              <p>
              create procedure select_lohnsumme(von_datum date, bis_datum date)
              returns
              ( nr integer,
              name varchar(30),
              vorname varchar(30),
              spanne double precision)
              as
              begin
              select nr, personal.name, personal.vorname, sum(spanne) from subselect_lohnarten(:von_datum, :bis_datum)
              join personal on (nr=personal.personalnr)
              group by nr, personal.name, personal.vorname
              into :nr, :name, :vorname, :spanne
              do suspend;
              end
              </pre>

              Das Select auf die StoredProc sieht dann nur noch so aus

              select nr, name, vorname, spanne from select_lohnsumme(von_datum date, bis_datum date)
              order by nr

              Ich gehe mal davon aus das es so auch mit dem IB 4.x funktioniert.

              Aus Performance-Gründen würde ich auch noch eine 3. StoredProc schreiben und damit die group-by-Klausel in der 2. StoredProc um Name + Vorname zu erleichtern.

              Tschüß

              Torste

              Comment


              • #8
                Hi Thorsten,<P>
                erstmal vielen Dank, daß sich noch jemand um mich bemüht. In der blöden Software, in der ich meine geringen SQL-Kenntnisse anwenden kann, habe ich nur die Möglichkeit, eine SELECT-Anw. und zwei StoredProc zu schreiben. Die beiden StoredProcs <B>müssen</B> temp und temp2 heißen.<BR>Also hab ich anstelle "create procedure subselect_lohnarten" "create procedure temp" und anstelle "create procedure select_lohnsumme" "...temp2" geschrieben.<BR>In der proc. select-lohnsumme habe ich dann bei dem select anstelle "...from subselect_lohnarten" "...from temp2" geschrieben.<P>Leider funzt das nicht, weil mir folgende Meldung ausgegeben wirdie Procedure temp2 konnte nicht erzeugt werden. Ich weiß nur nicht wieso. Kannst Du mir noch weiterhelfen? Gruß Sve

                Comment


                • #9
                  Hallo Sven,

                  ...Also hab ich anstelle "create procedure subselect_lohnarten" "create procedure temp" und anstelle "create procedure select_lohnsumme" "...temp2" geschrieben.
                  In der proc. select-lohnsumme habe ich dann bei dem select anstelle "...from subselect_lohnarten" "...from temp2" geschrieben...

                  Hast Du eventuell temp und temp 2 verwechselt?

                  Tschüß

                  Torste

                  Comment


                  • #10
                    Ich wollt's eigentlich im letzten Beitrag schon schreiben. Ich hab's natürlich sicherheitshalber auch andersrum probiert.<BR>
                    Gruß Sve

                    Comment


                    • #11
                      Hallo Sven,

                      wahrscheinlich unterstützt IB 4.x noch nicht den SQL 92-Standard.
                      Deshalb mußt Du den Join in die where-Klausel verlagern.

                      <pre>
                      create procedure temp2(von_datum date, bis_datum date)
                      returns
                      ( nr integer,
                      name varchar(30),
                      vorname varchar(30),
                      spanne double precision)
                      as
                      begin
                      select nr, personal.name, personal.vorname, sum(spanne) from temp(:von_datum, :bis_datum)
                      where nr=personal.personalnr
                      group by nr, personal.name, personal.vorname
                      into :nr, :name, :vorname, :spanne
                      do suspend;
                      end
                      </pre>

                      Wenn das alles nicht funktioniert werde ich wohl doch noch einmal den IB 4.x auf meinem Rechner installieren müssen. Derzeit habe ich nur den IB 6.0 sowie Firebird auf meinem anderen Computer installiert.

                      Tschüß

                      Torste

                      Comment


                      • #12
                        Hallo Torsten,<P>
                        leider funzt das auch nicht. Ich habe (wohl zum 1.000sten Mal) die Schreibweise überall verglichen - trotzdem klappt's nicht.<BR>Ich werde mal mit dem Software-Hersteller sprechen, ob es einen besonderen Trick bei der Erstellung zweier Proceduren gibt; denn egal was ich ausprobiere, immer kann temp2 nicht erstellt werden. Vielen Dank für Deine Hilfe. Ich weiß nicht, ob's Dich interessiert, aber ich werde Dir (wenn vorhanden) ein positives Resultat mitteilen.

                        Tschüß<P>
                        Sve

                        Comment


                        • #13
                          Hallo Sven,

                          ich habe mir nochmal den IB-Server 4.1 installiert und die 2 StoredProc auch nicht zum laufen bekommen.

                          Deshalb lassen wir mal die 2 StoredProc weg und machen dafür einen etwas umfangreichen Select von der Clienseite her.
                          <pre>
                          <b>
                          create procedure temp(von_datum date, bis_datum date)
                          returns
                          ( nr integer,
                          spanne double precision)
                          as
                          begin
                          for select personalnr, sum( preis * 0.5 ) from lohnarten
                          where ( lohnart=10 or lohnart=29 ) and
                          einspers.datumvon>=:EDatum_von AND
                          einspers.datumbis<=:EDatum_bis AND
                          personal.personalnr=auftrloa.personalnr AND
                          einspers.personalnr=auftrloa.personalnr AND
                          auftrloa.auftragnr=einspers.auftragnr
                          group by personalnr
                          into :nr, :spanne
                          do suspend;
                          for select personalnr, sum( preis * 1 ) from lohnarten
                          where ( lohnart<>10 and lohnart<>29 ) and
                          einspers.datumvon>=:EDatum_von AND
                          einspers.datumbis<=:EDatum_bis AND
                          personal.personalnr=auftrloa.personalnr AND
                          einspers.personalnr=auftrloa.personalnr AND
                          auftrloa.auftragnr=einspers.auftragnr
                          group by personalnr
                          into :nr, :spanne
                          do suspend;
                          end
                          <p>
                          und hier das Select-Statement aus Deinem Programm heraus:
                          <br>
                          select nr, personal.name, personal.vorname, sum(spanne) from temp(:von_datum, :bis_datum)
                          join personal on (nr=personal.personalnr)
                          group by nr, personal.name, personal.vorname
                          </pre></b>

                          Tschüß

                          Torste

                          Comment


                          • #14
                            Moin Torsten,<P>
                            hab Deinen SELECT noch etwas abgeändert, da die proc nicht erzeugt werden konnte. Jetzt wird sie erzeugt, ich gebe die beiden Daten ein, bekomme aber kein Ergebnis. Also keine Anzeige, einfach gar nichts. Meine Angaben über Tabellennamen und Spalten sind aber wirklich 100%-ig richtig. Noch 'ne Idee? Hier nochmal mein geänderter Code.<P>
                            <B>Mein select</B><BR>
                            select nr, personal.name, personal.vorname, sum(spanne) from temp([3von_datum], [3bis_datum])<BR>
                            join personal on (nr=personal.personalnr)<BR>
                            group by nr, personal.name, personal.vorname<P>
                            <B>Und hier die Procedure</B><BR>
                            (Evon_datum date, Ebis_datum date)<BR>
                            returns<BR>
                            (<BR>
                            nr integer, <BR>
                            spanne double precision<BR>
                            )<BR>
                            as <BR>
                            begin<BR>
                            for select auftrloa.personalnr, sum(preis * 0.5) from auftrloa, einspers, personal<BR>
                            where (lohnart=10 or lohnart=29) and <BR>
                            einspers.datumvon >= :Evon_datum AND <BR>
                            einspers.datumbis <= :Ebis_datum AND <BR>
                            personal.personalnr = auftrloa.personalnr AND <BR>
                            einspers.personalnr = personal.personalnr AND <BR>
                            auftrloa.auftragnr = einspers.auftragnr <BR>
                            group by auftrloa.personalnr <BR>
                            into :nr, :spanne <BR>
                            do suspend; <BR>
                            for select auftrloa.personalnr, sum(preis * 1) from auftrloa, einspers, personal<BR>
                            where (lohnart <> 10 and lohnart <> 29) and <BR>
                            einspers.datumvon >= :Evon_datum AND <BR>
                            einspers.datumbis <= :Ebis_datum AND <BR>
                            personal.personalnr = auftrloa.personalnr AND <BR>
                            einspers.personalnr = personal.personalnr AND <BR>
                            auftrloa.auftragnr = einspers.auftragnr <BR>
                            group by auftrloa.personalnr <BR>
                            into :nr, :spanne <BR>
                            do suspend; <BR>
                            end <P>
                            Anmerkung: Die 3 im select ([3von_datum....) muß ich so schreiben, damit das Programm die Eingabe als Datum annimmt und ebenso die erste Zeile in der Proc (Evon_datum date....)<P>
                            Vielen Dank erstmal<BR>
                            Tschüß<P>Sve

                            Comment


                            • #15
                              Hallo Sven,

                              schick mir mal ein Backup Deiner DB mit ein paar Testdaten (klick mal auf meinen Namen). Ansonsten werden wir wohl nur sehr langsam zum Ziel kommen.

                              Tschüß

                              Torste

                              Comment

                              Working...
                              X