Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Artikelpreis zu gegenem Datum (https://www.delphipraxis.net/60631-artikelpreis-zu-gegenem-datum.html)

Jelly 10. Jan 2006 10:47

Datenbank: MSSQL • Version: 2000 • Zugriff über: BDE

Artikelpreis zu gegenem Datum
 
Irgendwie häng ich ganz blöd bei einer SQL Abfrage.

Ich habe eine Tabelle Artikel, mit Feldern ID und Bezeichnung

Und eine Tabelle mit den aktuellen Artikelpreisen:
ID, Artikel, Preis, Datum

Soll heissen, im Laufe der Zeit kann sich ein Artikelpreis ändern. Das Datum in der Preis Tabelle ist der Wert, ab wann der angegebene Preis gültig ist.

Bsp: Artikel 1, 'Blubb'
Preise:
1, 1, 100, 01.01.2005
2, 1, 200, 01.01.2006
3, 1, 300, 01.01.2007

Ich brauche jetzt eine Liste mit allen Artikeln und allen korrekten Preisen zu einem gegebenem Datum, z.B. 01.02.2006.

Ich krieg das nicht hin. Ältere Preise krieg ich leicht weggefiltert, da ja das Suchdatum >= Preisdatum sein muss. Aber ich krieg den Eintrag 01.01.2007 mit Preisangabe 300 nicht weg aus dem Resultset.

Aenogym 10. Jan 2006 11:09

Re: Artikelpreis zu gegenem Datum
 
hi jelly,

du möchtest eine liste mit all deinen produkten haben, wo bei jedem produkt der preis eines bestimmten datums ist?

ich würde jetzt mal spontan folgendes vorschlagen:

SQL-Code:
SELECT a.Name, p.Preis
FROM artikel AS a
LEFT JOIN preise AS p ON p.Artikel = a.ID
WHERE p.Datum = '01.01.2006'
sollte doch funktionieren oder nicht?

aeno

tomsel 10. Jan 2006 11:28

Re: Artikelpreis zu gegenem Datum
 
Zitat:

Zitat von Aenogym
hi jelly,

du möchtest eine liste mit all deinen produkten haben, wo bei jedem produkt der preis eines bestimmten datums ist?

ich würde jetzt mal spontan folgendes vorschlagen:

SQL-Code:
SELECT a.Name, p.Preis
FROM artikel AS a
LEFT JOIN preise AS p ON p.Artikel = a.ID
WHERE p.Datum = '01.01.2006'
sollte doch funktionieren oder nicht?

aeno

Ich denke, es ist eher folgendes gemeint:

SQL-Code:
SELECT a.Name, p.Preis
FROM artikel AS a, preise AS p
WHERE p.Artikel = a.ID
AND p.Datum = MAX(SELECT p.Datum from artikel AS a, preise AS p where p.artikel = a.ID and p.Datum <= '01.01.2006')
Das sollen alle Artikel mit ihrem zum 01.01.2006 gültigen Preis sein, wenn ich das nicht total verkorkt hab.

sir-archimedes 10. Jan 2006 11:29

Re: Artikelpreis zu gegenem Datum
 
Nee das wird so einfach nicht funktionieren, da ja nicht jeden Tag der gültige Preis eingetragen wird. Das heißt man muss die letzte Aktualisierung vor dem Datum berücksichtigen.

Sowas könnte funktionieren:

SQL-Code:
DECLARE @Suchdatum datetime;
SET @Suchdatum = '01.01.2006'

SELECT a.Name, p.Preis
FROM artikel AS a
LEFT JOIN preise AS p ON p.Artikel = a.ID
WHERE p.Datum <= @Suchdatum AND
      p.Datum = (SELECT max(preise.Datum) FROM preise WHERE preise.Artikel = a.ID AND preise.datum <= @Suchdatum)
Das sollte dir das gewünschte Ergebnis liefern. (hoffe ich :))

sir-archimedes 10. Jan 2006 11:30

Re: Artikelpreis zu gegenem Datum
 
:spin2: zwei doofe ein Gedanke - und du warst schneller...

tomsel 10. Jan 2006 11:36

Re: Artikelpreis zu gegenem Datum
 
:dancer2:

sir-archimedes 10. Jan 2006 11:39

Re: Artikelpreis zu gegenem Datum
 
Ha aber deins wird nicht funktionieren :-D

Hier nämlich greifst du nicht mehr auf die ursprüngliche Artikel-Tabelle zu:

SQL-Code:
AND p.Datum = MAX(SELECT p.Datum from artikel AS a, preise AS p where p.artikel = a.ID and p.Datum <= '01.01.2006')
Du suchst damit nämlich einfach nur das maximale datum für alle Artikel raus und nicht für dein einen ;-)

:dancer:

tomsel 10. Jan 2006 11:53

Re: Artikelpreis zu gegenem Datum
 
Zitat:

Zitat von dominik.boehm
Ha aber deins wird nicht funktionieren :-D

Hier nämlich greifst du nicht mehr auf die ursprüngliche Artikel-Tabelle zu:

SQL-Code:
AND p.Datum = MAX(SELECT p.Datum from artikel AS a, preise AS p where p.artikel = a.ID and p.Datum <= '01.01.2006')
Du suchst damit nämlich einfach nur das maximale datum für alle Artikel raus und nicht für dein einen ;-)

:dancer:

na ja, as soll ich sagen? Also wohl doch nur ein Doofer! :stupid:

Aber warum machst du zwei mal "<=@Suchdatum" :?:

sir-archimedes 10. Jan 2006 11:58

Re: Artikelpreis zu gegenem Datum
 
Stimmt kann man weglassen (das obere). Das untere brauchst du, damit du das richtige "maximale" Datum raussuchst.

Jelly 10. Jan 2006 12:40

Re: Artikelpreis zu gegenem Datum
 
Also irgendwie kommt das noch nicht ganz hin. Ich habs aber jetzt über eine temporäre View gelöst. Eure Ansätze waren schon alle richtig, nur muss ich noch ein weiteres Kriterium berücksichtigen.

Aber jetzt scheints auch bei mir zu klappen... Danke für die Mühe.

Hansa 10. Jan 2006 20:53

Re: Artikelpreis zu gegenem Datum
 
Ich würde den Einsatz einer SP in Betracht ziehen, z.B. so :

SQL-Code:
ALTER PROCEDURE NETTOSP (
    BETRAG DECIMAL(15,2),
    MWSTSATZ SMALLINT,
    DATUM DATE)
RETURNS (
    GESNETTO DECIMAL(15,2))
AS
DECLARE VARIABLE MWSTPROZ DECIMAL(15,2);
BEGIN
  SELECT FIRST 1 MWSTWERT FROM MWST WHERE
    (MWSTSATZ=:MWSTSATZ) AND (ABDATUM <= :DATUM)
  ORDER BY ABDATUM DESC INTO :MWSTPROZ;
  IF (MWSTPROZ IS NULL) THEN MWSTPROZ = 0;
/*  GESNETTO = CAST (BETRAG / (1 + MWSTPROZ / 100) AS DECIMAL (15,2)); */
  GESNETTO = BETRAG / (1 + MWSTPROZ / 100);
  SUSPEND;
END
Da gehts zwar um die Ermittlung der Mwst., aber das dürfte egal sein. Es ist halt datumsgesteuert. Ob Mickysoft-SQL allerdings so was hat wie SELECT FIRST ? :gruebel: In Firebird gibts das auch erst seit vorletzter Version.

alzaimar 10. Jan 2006 20:59

Re: Artikelpreis zu gegenem Datum
 
Zitat:

Zitat von Hansa
...Ob Mickysoft-SQL allerdings so was hat wie SELECT FIRST ? :gruebel:

Mach Dir man keine Sorgen (SELECT TOP 1...), MSSQL ist um längen schneller, mächtiger, skalierbarer, robuster und besser als Firebird & Co. :mrgreen:

Elvis 10. Jan 2006 22:16

Re: Artikelpreis zu gegenem Datum
 
Zitat:

Zitat von alzaimar
Mach Dir man keine Sorgen (SELECT TOP 1...), MSSQL ist um längen schneller, mächtiger, skalierbarer, robuster und besser als Firebird & Co. :mrgreen:

Wurde aber erst mit dem aktuellen 2005'er aus Sicht einer Oracle-verwöhnten Göre interesant. Alle Versionen vorher waren zumindest im Transaktionsmodell einfach peinlich. ;)
FB scheint sich mit jedem bisschen was sie von Interbase rausschmeißen zu verbessern. ;)

@Topic
Eine selectable Procedure wäre hier nun wirklich witzlos, auch wennn SQL ziemlich schnell ziemlich eklig wird, wenn es um Aggregationen geht. (hässlich ist es ja sowieso immer ;) )

Als Erbchleicher wäre wahrscheinlich eine Liste der Ids aller Preise ausreichend um bereits vorher geholte Instanzen der Preise wiederzufinden:
SQL-Code:
SELECT p.Id
FROM Artikel a
     INNER JOIN Preise p ON p.Artikel = a.ID
     INNER JOIN Preise filter ON p.Artikel = a.ID
WHERE filter.Datum <= @Suchdatum
GROUP BY p.Id, p.Datum
HAVING p.Datum = max(filter.Datum)
Als RADieschen braucht man mehr Spalten, wodurch die Gruppierung aufwendiger wäre als die SubQuery aus Dominiks Beispiel. (MSSQL hatte vor 2005 leider den Hang dazu, SubQueries gerne mal für jeden Datensatz zu neu abzufragen :? )

Hansa 10. Jan 2006 23:19

Re: Artikelpreis zu gegenem Datum
 
Zitat:

Zitat von alzaimar
...keine Sorgen (SELECT TOP 1...), MSSQL ist um längen schneller, mächtiger, skalierbarer, robuster und besser als Firebird & Co. :mrgreen:

Wenn First/Top dasselbe macht, dann ists ja auch gut so. Mickysoft-SQL war letztlich für den Einsatzweck immerhin 2. Wahl. Wegen mangelnder Skalierbarkeit, geringerem Sprachumfang, schlechterer Transaktionssteuerung usw. :mrgreen:

alzaimar 11. Jan 2006 06:45

Re: Artikelpreis zu gegenem Datum
 
Zitat:

Zitat von Hansa
...war letztlich für den Einsatzweck immerhin 2. Wahl. Wegen mangelnder Skalierbarkeit, geringerem Sprachumfang, schlechterer Transaktionssteuerung usw. ...

So so.

Jelly 11. Jan 2006 07:40

Re: Artikelpreis zu gegenem Datum
 
Zitat:

Zitat von Elvis
Als Erbchleicher wäre wahrscheinlich eine Liste der Ids aller Preise ausreichend um bereits vorher geholte Instanzen der Preise wiederzufinden:
SQL-Code:
SELECT p.Id
FROM Artikel a
     INNER JOIN Preise p ON p.Artikel = a.ID
     INNER JOIN Preise filter ON p.Artikel = a.ID
WHERE filter.Datum <= @Suchdatum
GROUP BY p.Id, p.Datum
HAVING p.Datum = max(filter.Datum)

So in der Art hab ich da jetzt auch gelöst, nur anders :zwinker:

Ich hab mir als Erstes eine temporäre View erstellt:
SQL-Code:
create view vwPreiseHeuteTemp
as
SELECT    fiArtikel, ISNULL(MAX(Datum), GETDATE() AS Datum, EKVK
FROM        dbo.Preise
WHERE    (Datum <= GETDATE())
GROUP BY fiArtikel, EKVK
HAVING     (MAX(Datum) <= GETDATE())
Für die eigentlich Abfrage greif ich dann über joins auf diese View zu, weil ich noch aus anderen Tabelle etliches Zeusch brauch. Aber im Grunde ist obige temporäre View schon das, was das Problem löst.

alzaimar 11. Jan 2006 07:55

Re: Artikelpreis zu gegenem Datum
 
Du kannst es auch so lösen:
SQL-Code:
Select ID,
      Bezeichnung,
      (select top 1 preis
         from Preise
        where Preise.ID = Artikel.ID and Preise.Datum <= '1.1.2006'
        order by Preise.Datum desc
      )
from Artikel
Die ORDER BY Klausel macht die Abfrage langsam. Wenn Du einen Clustered Index auf Preise.Datum setzt, ist die Welt aber wieder in Ordnung,weil das ORDER BY dann weggekürzt wird.

Das würde ich für die schnellste und einfachste Lösung halten.

Hansa 11. Jan 2006 19:22

Re: Artikelpreis zu gegenem Datum
 
Ah, Alzaimar hat mein Beispiel konkretisiert. Und ich habe mal in der richtigen Datenbank nachgeguckt, wie das geht :

Delphi-Quellcode:
CREATE PROCEDURE ERRECHNEPREIS (
    ID_ART INTEGER,
    PGNR SMALLINT,
    ABDATUM DATE)
RETURNS (
    PREIS DECIMAL(15,2))
AS
BEGIN
  SELECT FIRST 1 PREIS FROM ARTPG WHERE
    (PGNR=:PGNR) AND (ABDATUM <= :ABDATUM)
  ORDER BY ABDATUM DESC INTO :PREIS;
  IF (PREIS IS NULL) THEN PREIS = 0;
  SUSPEND;
END^
PG steht für Artikel-Preisgruppe (extra Tabelle). Ist der Preis direkt dem Artikel zugeordnet, dann gehts noch kürzer. Der bisher gezeigte Code ist IMHO zu kompliziert / unleserlich für den Zweck.

Jelly 11. Jan 2006 19:55

Re: Artikelpreis zu gegenem Datum
 
@Hansa: Deine Procedure liefert mir aber nur den Preis eines Artikels. Ich brauche aber eine Liste (Resultsut) von allen Artikeln und dem zugehörigem Preis zu gegebenem Datum.

Aber meine Lösung klappt ja mittlerweilen, warum noch lange rumexperimentieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:21 Uhr.

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