SQLite Preisliste mit Standardpreisen und kundenspezifischen Preisen

Mat

Aktives Mitglied
Moin, ich komme grad nicht darauf, wie ich das am besten lösen könnte. Es läuft, aber habe eine Denkblockade und weiß nicht, ob es korrekt ist:

Anwendungsfall​

Zur Erstellung von Angeboten/Rechnungen wird in einer DB nach hinterlegten Preisen gesucht. Diese sind in einer Preisliste hinterlegt. Einige Kunden haben für einige Produkte eigene Preise. Diese sollen dann anstelle der normalen Preise benutzt werden.

Nun würde ich gerne eine Kundenspezifische Preisliste als View haben.

Beispiel​

Habe ein vereinfachtes Beispiel erstellt, mit Kundenfilter in einer Filtertabelle:

vSpeziFisch:
SELECT "SP".id, "SP".preis AS "STANDARDPREIS",
    "KP".kd_id,  "KP".preis AS "KUNDENPREIS",
    (CASE
        WHEN "KP".preis > 0 THEN "KP".preis
        ELSE "SP".preis
    END) AS "EFFEKTIVER_PREIS"
    , "FLTR".*   
FROM "Standardpreise" "SP"
LEFT JOIN "Filter" "FLTR" ON "FLTR".schluessel = 'KUNDE'
LEFT JOIN "Kundenpreise" "KP" ON
    "SP".id = "KP".preis_id AND "KP".kd_id = "FLTR".wert;

Ergebnis mit Filter auf kd_id=2 :​


idSTANDARDPREISkd_idKUNDENPREISEFFEKTIVER_PREISschluesselwert
110288KUNDE2
22020KUNDE2
33030KUNDE2
44040KUNDE2
55050KUNDE2
66060KUNDE2
77070KUNDE2
88080KUNDE2
99090KUNDE2
101002125125KUNDE2


Scheint zu klappen. Wenn ich den Kundenfilter auf NULL setze, zeigt er mir auch eine ganz normale Preisliste ohne Kundenpreise. Aber ist das vielleicht zu umständlich gedacht?

Falls Details benötigt werden:​

DB mit Daten:
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS "Standardpreise" (
    "id"    INTEGER NOT NULL UNIQUE,
    "preis"    NUMERIC DEFAULT 0.0,
    PRIMARY KEY("id" AUTOINCREMENT)
);
CREATE TABLE IF NOT EXISTS "Kundenpreise" (
    "preis_id"    INTEGER NOT NULL,
    "kd_id"    INTEGER NOT NULL,
    "preis"    NUMERIC DEFAULT 0.0,
    PRIMARY KEY("preis_id","kd_id")
);
CREATE TABLE IF NOT EXISTS "Kunden" (
    "id"    INTEGER NOT NULL UNIQUE,
    "name"    TEXT,
    PRIMARY KEY("id" AUTOINCREMENT)
);
CREATE TABLE IF NOT EXISTS "Filter" (
    "schluessel"    TEXT NOT NULL UNIQUE,
    "wert"    INTEGER,
    PRIMARY KEY("schluessel")
);
INSERT INTO "Standardpreise" VALUES (1,10);
INSERT INTO "Standardpreise" VALUES (2,20);
INSERT INTO "Standardpreise" VALUES (3,30);
INSERT INTO "Standardpreise" VALUES (4,40);
INSERT INTO "Standardpreise" VALUES (5,50);
INSERT INTO "Standardpreise" VALUES (6,60);
INSERT INTO "Standardpreise" VALUES (7,70);
INSERT INTO "Standardpreise" VALUES (8,80);
INSERT INTO "Standardpreise" VALUES (9,90);
INSERT INTO "Standardpreise" VALUES (10,100);
INSERT INTO "Kundenpreise" VALUES (1,1,5);
INSERT INTO "Kundenpreise" VALUES (1,3,11);
INSERT INTO "Kundenpreise" VALUES (2,1,18.5);
INSERT INTO "Kundenpreise" VALUES (10,2,125);
INSERT INTO "Kundenpreise" VALUES (1,2,8);
INSERT INTO "Kunden" VALUES (1,'Horst');
INSERT INTO "Kunden" VALUES (2,'Peter');
INSERT INTO "Kunden" VALUES (3,'Astrid');
INSERT INTO "Filter" VALUES ('KUNDE',2);
CREATE VIEW "vSpeziFisch" AS SELECT
    "SP".id,
    "SP".preis AS "STANDARDPREIS",
    "KP".kd_id,
    "KP".preis AS "KUNDENPREIS",
    (CASE
        WHEN "KP".preis > 0 THEN "KP".preis
        ELSE "SP".preis
    END) AS "EFFEKTIVER_PREIS"
    , "FLTR".*   
FROM "Standardpreise" "SP"
LEFT JOIN "Filter" "FLTR" ON "FLTR".schluessel = 'KUNDE'
LEFT JOIN "Kundenpreise" "KP" ON
    "SP".id = "KP".preis_id AND "KP".kd_id = "FLTR".wert;
COMMIT;
 

Jan Krüger

Neues Mitglied
Prinzipiell sieht das vernünftig aus, auch wenn mir der Zweck der Filter-Tabelle nicht klar ist. Du kannst allerdings das CASE ersetzen durch: COALESCE(KP.preis, SP.preis)
 

Mat

Aktives Mitglied
Danke für das Feedback. Beim Beispiel scheint es zu funktionieren, aber beim Originalfall habe ich noch fehlerhafte Ausgabe und muss die mir im Detail ansehen. Vielleicht morgen oder so. Ich versuche dann, das Beispiel anzupassen.

Prinzipiell sieht das vernünftig aus, auch wenn mir der Zweck der Filter-Tabelle nicht klar ist. Du kannst allerdings das CASE ersetzen durch: COALESCE(KP.preis, SP.preis)

Zumindest bei SQLite wird dann 0 als gültiger Wert betrachtet und überschreibt den Standardpreis. Weil es durch Fehleingaben des Users dazu kommen kann, wollte ich diese Preise ausschließen. Deswegen brauche ich da den CASE.

Ich experimentiere grad etwas mit LibreOffice Base.
Der Kram mit dem Filter ist so eine Eigenheit von Base. Das hängt ein bisschen mit dem Aufbau von Formularen und dem Databinding und Subformularen zusammen. Ich finde das Prinzip nicht so gut, habe es aber erst einmal so übernommen, weil es viele Base-Probleme löst und da auch als "Best Practice" betrachtet wird. :unsure:

Edit: Ich konnte den gestrigen Fehler nicht reproduzieren. Vermutlich war da noch was im Cache bzw wurde die Datensatzaktion nicht richtig committet. Scheint alles zu laufen. Danke nochmal
 
Zuletzt bearbeitet:
Oben Unten