Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Subquery mit mehreren Results (https://www.delphipraxis.net/130319-subquery-mit-mehreren-results.html)

Ykcim 6. Mär 2009 11:33

Datenbank: MySQL • Version: 5 • Zugriff über: C-Api

Subquery mit mehreren Results
 
Hallo Zusammen,

ich hoffe, Ihr könnt mir helfen. Eine Subquery, die mehrere Results zurückliefert, funzt nicht.
Was will ich machen?

Jeder Benutzer hat die Möglichkeit, Aufträge für Artikel auf beobachten zu setzen. Wenn sich der Benutzer im Programm anmeldet, bekommt er nur die Liste, mit seinen beobachteten Artikeln. Gelöst mit einer Beobachten-Tabelle, in die die Auftragsnummern und die USERID geschrieben wird.

SQL-Code:
select Artikelstammdaten.ArtikelNr from Beobachten
join Artikelstammdaten on Beobachten.ArtikelNr=Artikelstammdaten.ArtikelNr
where UserID=1
So weit so gut

In einer anderen Tabelle habe ich für jeden Artikel mehrere Lagerorte und die entsprechenden Lagerbestände.

Ich möchte, dass jeder Benutzer in seiner Liste der beobachteten Aufträge auch sieht, wie hoch in Summe der Lagerbestand.

Meine Abfrage für einen Artikel müsste also lauten:
SQL-Code:
Select ArtikelNr, sum(Lagerbestand) from Lager
where ArtikelNr=(select Artikelstammdaten.ArtikelNr from Beobachten
join Artikelstammdaten on Beobachten.ArtikelNr=Artikelstammdaten.ArtikelNr
where UserID=1)
Aber das funktioniert bekanntlich nicht, da die Subquery mehr als eine ArtikelNr zurückgibt...

Wie kann ich das lösen?

Vielen Dank im Voraus

Ykcim

DeddyH 6. Mär 2009 11:38

Re: Subquery mit mehreren Results
 
Ohne groß nachgedacht zu haben:
SQL-Code:
Select ArtikelNr, sum(Lagerbestand) from Lager
where ArtikelNr IN (select...

Ykcim 6. Mär 2009 11:52

Re: Subquery mit mehreren Results
 
Hallo DeddyH

Vielen Dank für Deine schnelle Antwort!

So habe ich es probiert:
SQL-Code:
select WATENR, sum(LSLGBE) as Lagerbestand from oms14
where WATENR in
(select as400.WATENR from beobachten
join as400 on beobachten.WAAUNR= as400.WAAUNR
where UserID=1)
Leider bekomme ich die Fehlermeldung:
Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause

Hast Du da eine Erklärung für? Für sich genommen funktioniert die Subquery...

Danke

Ykcim

DeddyH 6. Mär 2009 11:55

Re: Subquery mit mehreren Results
 
Da fehlt ja auch die Gruppierung. Wie spielt da eigentlich die Stammdatentabelle mit rein, das hab ich noch nicht ganz verstanden. Ginge das nicht auch einfach so?
SQL-Code:
SELECT
  Beobachten.ArtikelNr, sum(Lager.Lagerbestand)
FROM
  Beobachten
JOIN
  Lager ON Lager.ArtikelNr = Beobachten.ArtikelNr
WHERE
  Beobachten.UserID=1
GROUP BY
  Beobachten.ArtikelNr
ORDER BY
  Beobachten.ArtikelNr

Ykcim 6. Mär 2009 12:01

Re: Subquery mit mehreren Results
 
In der Beobachtenliste stehen die ArtikelNr nicht drin, sondern nur die Auftragsnummern. Daher muss ich mir erst die entsprechende ArtikelNr aus den Stammdaten holen. (Die Tabelle Stammdaten wird regelmäßig mit Daten aus dem PPS gefüllt...)


Gruß
Ykcim

Ykcim 6. Mär 2009 12:04

Re: Subquery mit mehreren Results
 
Ach ja, die Fehlermeldung ist begründet in der Summenabfrage. Wenn ich die heruasnehme, dann bekomme ich einmal die beiden ArtikelNr zurück, die in der Beobachten Tabelle stehen, obwohl sie in der Stammdatentabelle sehr viel öfter stehen (Der Begriff Stammdaten ist verwirrend, besser wäre der Begriff Auftragsliste)...

DeddyH 6. Mär 2009 12:05

Re: Subquery mit mehreren Results
 
In Deinen bislang geposteten Statements taucht aber keine Auftragsnummer auf :gruebel: Zeig doch mal die Tabellenstruktur mit den relevanten Feldern (Fremdschlüssel), dann verstehe ich die Zusammenhänge auch besser.

Ykcim 6. Mär 2009 12:08

Re: Subquery mit mehreren Results
 
Okay, ich versuche jetzt das gesamte Problem darzustellen, aber das dauert eine Weile, weil wir uns hier nur einen kleinen Teilbereich bewegen...

Melde mich gleich wieder

Ykcim

Ykcim 6. Mär 2009 12:21

Re: Subquery mit mehreren Results
 
Also, das Programm beschäftigt sich mit der Terminverfolgung von Fertigungsaufträgen. Dazu werden drei Tabellen mit Daten aus dem ERP-System bestückt:

Auftragsdaten: AuftragsNr, ArtikelNr, Fertigungsmenge, ArbeitsgangNr
Kundebedarf: ArtikelNr, Bedarfsmenge, Liefertermin, Kunde
Lagerbestand: ArtikelNr, Lagerort, Lagermenge

Jeder Auftrag hat mehrere Arbeitsgänge, dass heißt, dass eine Auftragsnummer öfter in der tabelle Auftragsdaten (bislang Artikelstamm)

Ich möchte aufzeigen, welcher Auftrag bis wann fertig sein muss.


Dazu muss ich den Lagerbestand gegen die Kundbedarfe laufen lassen und gucken, wann der Lagerbestand durch 0 läuft. Spätestens dann müssen so viele Aufträge fertig sein, dass der Kundenbedarf gedeckt werden kann. (es kann nicht Kundenauftragsbezogen gefertigt werden, da das mit den Fertigungsmengen nicht vereinbar ist).

Wenn also der Lagerbestand durch 0 läuft müssen für die Aufträge, die am weitesten fertig sind, das Enddatum auf den Liefertermin gesetzt werden. Und so kann ich für alle Aufträge das erforderliche Enddatum berechnen und ausgeben.

Wenn ich nach einem Artikel suche, habe ich das wie folgt gelöst.
Delphi-Quellcode:
procedure TFA_suchen.suchenClick(Sender: TObject);
var query, query1, query2, query3 : string;
    Cols, Cols1, Cols2, Cols3 : TCols;
    Rows, Rows1, Rows2, Rows3 : TRows;
    i, j, k :integer;
begin
//Lagerbestand
query:= 'select sum(lslgbe)from oms14 '+
        'where watenr= '+Kriterium.Text;
MenueUnit.connect;
MenueUnit.ExecQuery(DB, query, cols, Rows);
//======================================}
//Kundenbedarf
query1:= 'select omslp.WATENR as ArtikelNr, as400.TEBEZ1 as Bezeichnung, omslp.liefer as Kd_Bedarf, '+
          'DATE_FORMAT(omslp.ltlite,'+#39+'%d.%m.%Y'+#39+') as Kd_L_Datum, omslp.LTKDNR as Kd_Nr, omslp.KDKUNA as Kunde, '+
          'omslp.ltbdmg*0 as L_Bestand_kum from omslp '+
          'left join as400 on omslp.watenr=as400.watenr '+
          'where omslp.watenr= '+ Kriterium.Text +
          ' group by omslp.ltlite order by omslp.ltlite';
MenueUnit.ExecQuery(DB, query1, cols1, Rows1);
//======================================}
//Fertigungsaufträge
query2:= 'Select as400.WAAUNR as FA_Nr, as400.WAAUPO as Me_Bearb, as400.WATENR as ArtikelNr, as400.TEBEZ1 as Bezeichnung, as400.OAAGNR as AG_Nr, as400.OAAGBZ as Arbeitsgang_Bezeichnung, '+
          'REPLACE(FORMAT(as400.WAFEMG, 0),'+#39+','+#39+','+ #39+ '.'+#39+') as FA_Menge, as400.OAAGNR*0 as Lagerzugang, as400.WAFEMG, eilfa.angeschoben from as400 '+
          'left join eilfa on as400.WAAUNR=eilfa.WAAUNR and as400.WAAUPO=eilfa.WAAUPO '+
          'where OATLKZ <> 9 and WATENR= '+ Kriterium.Text + ' and WASTAT<> 50' +
          ' GROUP BY as400.WATENR, as400.WAAUNR '+
          'ORDER BY as400.WATENR, as400.OAAGNR DESC';
MenueUnit.ExecQuery(DB, query2, cols2, Rows2);
//======================================}
//Lagerzugangsdatum
i:=0; j:=0;
if AffectedRows > 0 then                      //Nur wenn es ein Ergebnis gibt
  begin
    rows1[6,i]:=inttostr(strtoint(rows[0,0])-strtoint(rows1[2,0]));
    if strtoint(rows1[6,0])<0  then
          begin
                while (strtoint(rows1[6,0])<0) and (j<length(rows2[0])) do
                  begin
                    //Lagerzugangsdatum
                    rows2[7,j]:=datetostr(strtodate(rows1[3,0])-3);
                    //Fertigungsmenge zu rows1[3,i] addieren
                    rows1[6,0]:=inttostr(strtoint(rows1[6,0])+strtoint(rows2[8,j]));
                    // j+1
                    j:=j+1;
                  end;
          end;
    for i := 1 to length(rows1[0]) - 1 do
      begin
        rows1[6,i]:=inttostr(strtoint(rows1[6,i-1])-strtoint(rows1[2,i]));
        if (strtoint(rows1[6,i])<0) and (strtoint(rows1[6,i-1])>=0) then
          begin
                while (strtoint(rows1[6,i])<0) and (j<length(rows2[0])) do
                  begin
                    //Lagerzugangsdatum
                    rows2[7,j]:=datetostr(strtodate(rows1[3,i])-3);
                    //Fertigungsmenge zu rows1[3,i] addieren
                    rows1[6,i]:=inttostr(strtoint(rows1[6,i])+strtoint(rows2[8,j]));
                    // j+1
                    j:=j+1;
                  end;
          end;
      end;
  end
else
  begin
    MenueUnit.ClearGrid(FAs);
    MenueUnit.ClearGrid(DetailFA);
    MenueUnit.ClearGrid(KdBedarf);
  end;
//Kundenbedarf mit Tausendertrennzeichen
query3:= 'select REPLACE(FORMAT(omslp.ltbdmg, 0),'+#39+','+#39+','+ #39+ '.'+#39+') as Kd_Bedarf from omslp '+
          'where omslp.watenr= '+ Kriterium.Text +
          ' group by omslp.ltlite order by omslp.ltlite';
MenueUnit.ExecQuery(DB, query3, cols3, Rows3);

  if AffectedRows > 0 then                      //Nur wenn es ein Ergebnis gibt
    begin
      MenueUnit.FillGrid(FAs, Cols2, Rows2);
      for k := 0 to length(rows1[0]) - 1 do
        begin
           rows1[2,k]:=rows3[0,k];
        end;
      MenueUnit.FillGrid(KdBedarf, Cols1, Rows1);
      FAs.ColWidths[0]:= 50;
      FAs.ColWidths[1]:= 65;
      FAs.ColWidths[2]:= 60;
      FAs.ColWidths[3]:= 170;
      FAs.ColWidths[4]:= 50;
      FAs.ColWidths[5]:= 170;
      FAs.ColWidths[6]:= 70;
      FAs.ColWidths[7]:= 85;
      FAs.ColWidths[8]:= 0;
      FAs.ColWidths[9]:= 0;
      KdBedarf.ColWidths[0]:=65;
      KdBedarf.ColWidths[1]:=175;
      KdBedarf.ColWidths[2]:=90;
      KdBedarf.ColWidths[3]:=90;
      KdBedarf.ColWidths[4]:=60;
      KdBedarf.ColWidths[5]:=175;
      KdBedarf.ColWidths[6]:=115;
    end;
end;
Jetzt muss ich das ganze aber realisieren für eine ganze Liste an Aufträgen gleicher und unterschiedlicher Artikel.

Ist mein Problem jetzt deutlicher geworden?

Lieben Gruß

Ykcim

neo4a 6. Mär 2009 12:26

Re: Subquery mit mehreren Results
 
Wie wäre es mit dem IN- Operator, etwa so:

SQL-Code:
Select ArtikelNr, sum(Lagerbestand) from Lager
where ArtikelNr in (select Artikelstammdaten.ArtikelNr from Beobachten
join Artikelstammdaten on Beobachten.ArtikelNr=Artikelstammdaten.ArtikelNr
where UserID=1)
HTH.

--
Andreas


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:03 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz