SQL Abfrage Filter erweitern

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Peter1977
User
Beiträge: 86
Registriert: Mittwoch 4. September 2013, 14:59

Hallo,

Habe Drei Tabellen

Tabelle A
Spalte ID
Spalte Wert

Tabelle B
Spalte ID
Spalte TabelleA_ID
Spalte Wert

Tabelle C
Spalte ID
Spalte TabelleB_ID
Spalte Wert 1
Spalte Wert 2

Im Formular gibt es dann 2 Comboboxen und Eingabe Felder

Combobox A = Tabelle A
Combobox B = Tabelle B

Die 2 Comboboxen werden über Tabelle A und Tabelle B gefüllt
Wenn die Combobox A gefüllt ist bzw. ausgewählt wurde
wird die Combobox B nur mit passenden Werten gefüllt.

Ebenso werden die Werte aus Tabelle B die schon in der Tabelle C vorkommen
herausgefiltert.

dies Funktioniert

Jetzt sollen auch die Werte aus Tabelle A weggefiltert werden wenn in Tabelle B schon alle weggefiltert wurden.
der bisherige SQL Code

Tabelle A Combobox A

Code: Alles auswählen

SELECT id,lager_ort 
FROM lager_lager_ort
ORDER BY lager_ort;
Tabelle B Combobox B

Code: Alles auswählen

SELECT id,lagerplatz 
FROM lager_lager_platz 
WHERE lager_ort='%s' 
AND lager_lager_platz.id NOT IN (SELECT lager_lagerstand.lagerplatz FROM lager_lagerstand) 
ORDER BY lagerplatz;%(Ort_ID)
Hoffe es ist nicht zu Kompliziert und es hat einer eine Idee

mfg Peter
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Hoffe es ist nicht zu Kompliziert
Doch, ist es, bzw. es ist IMHO verwirrend.

Besonders die Zeile `AND lager_lager_platz.id NOT IN (SELECT lager_lagerstand.lagerplatz FROM lager_lagerstand)` sieht doch komisch was, also vom Datenbankdesign.

Was vielleicht helfen würde ist, wenn du mal _konkret_ deine aktuelle Tabellenstruktur beschreibst (oder die `CREATE TABLE`Statements postest) und erklärst, was du da genau wie verwalten willst.

Gruß, noisefloor
Peter1977
User
Beiträge: 86
Registriert: Mittwoch 4. September 2013, 14:59

Hallo,

Tabelle Lager Ort

Code: Alles auswählen

REATE TABLE lager_lager_ort
(
  id bigserial NOT NULL,
  lager_id integer NOT NULL,
  lager_ort character varying(20) NOT NULL,
  CONSTRAINT lager_lager_ort_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE lager_lager_ort
  OWNER TO postgres;
Tabelle Lager Platz

Code: Alles auswählen

CREATE TABLE lager_lager_platz
(
  id bigserial NOT NULL,
  lager_ort integer NOT NULL,
  lagerplatz character varying(15) NOT NULL,
  CONSTRAINT lager_lager_platz_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE lager_lager_platz
  OWNER TO postgres;
Tabelle Lagerstand

Code: Alles auswählen

CREATE TABLE lager_lagerstand
(
  id bigserial NOT NULL,
  artikel integer NOT NULL,
  lagerplatz integer NOT NULL,
  menge numeric(10,0) NOT NULL,
  CONSTRAINT lager_lagerstand_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE lager_lagerstand
  OWNER TO postgres;
Hoffe es ist ein wenig klarer

mfg Peter
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

Frage: du hast drei unabhängige Tabelle - warum verwendest du keine Relation via Fremdschlüssel? Mann kann Lagerplatz zu Lagerort ja in Relation setzen und auch Lagermenge zu Lagerplatz.

Dann könntest du auch die Abfragen entsprechend gestalten.

Und der Einsatz eines ORM wie SQLAlchemy könnte sich hier auch anbieten.

Gruß, noisefloor
Peter1977
User
Beiträge: 86
Registriert: Mittwoch 4. September 2013, 14:59

Hallo,
du keine Relation via Fremdschlüssel?
Hat mir immer wieder Probleme bereitet wenn die Tabellen Struktur auf Produktiv Server kopiert wurden.
bzw. die Datenstruktur auf den Test Server Kopiert wurde.

mfg Peter
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Hat mir immer wieder Probleme bereitet wenn die Tabellen Struktur auf Produktiv Server kopiert wurden.
Aha... heißt konkret? "Probleme" kann ja alles sein...

In gegebenen Fall ist es aber _sehr_ empfehlenswert, weil die Relation sind ja der Grund bzw. die Stärke von RDBMS.

Gruß, noisefloor
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Peter1977 hat geschrieben:
du keine Relation via Fremdschlüssel?
Hat mir immer wieder Probleme bereitet wenn die Tabellen Struktur auf Produktiv Server kopiert wurden.
bzw. die Datenstruktur auf den Test Server Kopiert wurde.
Das ist in etwa so als wenn man sagt, dass man es vermeidet, Module in seinen Python-Programmen zu importieren, weil das beim Ausführen auf einem anderen Rechner manchmal zu Problemen führt.

Was ich sagen will: Relationen sind ein absolutes Basismerkmal von den meisten Datenbanken. Wenn man dieses Merkmal umgeht, dann hat man etwas Grundlegendes nicht verstanden bzw nutzt die Vorteile des Merkmals nicht. Und dann muss man schon fast überlegen, ob nicht ein paar CSV-Dateien oder ein simpler Key-Value-Store ausreichen. Das wäre weniger komplex in der Handhabung als ein DBMS.

Falls du auf Probleme stößt, sobald mehr als nur eine Tabelle verwendet wird, dann wurde vielleicht etwas falsch kopiert oder gar nicht kopiert. Dann sollte man sich besser einmal hinsetzen und sich mit den Ursachen befassen, finde ich.

So wie es jetzt ist, haben deine Tabellen jedenfalls kaum einen Mehrwert. Sobald man der Tabelle `lager_lagerstand` als zusätzliche Spalte den Lagerort hinzufügt, sind alle Informationen aus den anderen beiden Tabellen in dieser einen Tabelle ausgedrückt. Das ist offen gesagt ein sehr fragwürdiges Design und entspricht auch nicht dem, wozu SQL eigentlich gedacht ist. Wie gesagt: Hier täte es dann auch eine schlichte CSV-Datei. Die kann man z.B. mit dem `csv`-Modul in Python dann durchgehend anpassen.
Peter1977
User
Beiträge: 86
Registriert: Mittwoch 4. September 2013, 14:59

Hallo,

Aha... heißt konkret? "Probleme" kann ja alles sein...

In gegebenen Fall ist es aber _sehr_ empfehlenswert, weil die Relation sind ja der Grund bzw. die Stärke von RDBMS.
Tabelle A hatte einen Fremdschlüssel von Tabelle B
Bei einem Backup von der kompletten DB nur Daten und dem darauf folgenden Einfügen in die Test DB war als erstes Tabelle A
Erste Datensatz wurde in die Tabelle Eingefügt und dann kam ähnlich "Datensatz in Tabelle B nicht vorhanden."

mfg Peter
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

dann hast du halt irgendwie irgendwas falsch gemacht. Wenn du die Tabellen mit Relationen baust, dann musst du auf jeden Falls alles 1x neu schreiben. "on the fly" geht die Änderung nicht.

Und hör' doch mal bitte auf, abstrakt von Tabelle A, Tabelle B zu reden - das bringt nichts. Das an konkreten Beispielen wie Lagerort, -platz etc. durchzuspielen ist wesentlich besser und besser nachzuvollziehen. Denn dann wäre IMHO z.B. der Lagerort ein Fremdschlüssel in der Tabelle Lagerplatz.

So, wie es jetzt ist, ist es jedenfalls IMHO "broken by design" - warum, hat snafu ja schon erklärt.

Gruß, noisefloor
Peter1977
User
Beiträge: 86
Registriert: Mittwoch 4. September 2013, 14:59

Hallo,

Tabellen mal Neu aufgestellt
Tabelle Lager
CREATE TABLE lg_lager
(
id bigserial NOT NULL,
lager character varying(25),
CONSTRAINT primary_lg_lager PRIMARY KEY (id),
CONSTRAINT unique_lager UNIQUE (lager)
)
WITH (
OIDS=FALSE
);
ALTER TABLE lg_lager
OWNER TO postgres;
Tabelle Lagerort
CREATE TABLE lg_lagerort
(
id bigserial NOT NULL,
lager_id bigint,
lagerort character varying(25),
CONSTRAINT primary_lagerort PRIMARY KEY (id),
CONSTRAINT "fremdschlüssel_lager_id" FOREIGN KEY (lager_id)
REFERENCES lg_lager (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE lg_lagerort
OWNER TO postgres;
Tabelle Lagerplatz
CREATE TABLE lg_lagerplatz
(
id bigserial NOT NULL,
lagerort_id bigint,
lagerplatz character varying(25),
CONSTRAINT primary_lagerplatz PRIMARY KEY (id),
CONSTRAINT fremd_lagerort_id FOREIGN KEY (lagerort_id)
REFERENCES lg_lagerort (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE lg_lagerplatz
OWNER TO postgres;
Tabelle Lagerstand
CREATE TABLE lg_lagerstand
(
id bigserial NOT NULL,
lagerplatz_id bigint,
artikel_id bigint,
menge numeric(5,0),
CONSTRAINT primary_lagerstand PRIMARY KEY (id),
CONSTRAINT fremd_artikel_id FOREIGN KEY (artikel_id)
REFERENCES lg_lager (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fremd_lagerplatz_id FOREIGN KEY (lagerplatz_id)
REFERENCES lg_lagerplatz (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE lg_lagerstand
OWNER TO postgres;
Hoffe das dies mal Besser passt

mfg Peter
BlackJack

@Peter1977: Das die letzte Tabelle wieder die erste Referenziert und den Fremdschlüssel `artikel_id` nennt, scheint mir falsch zu sein.
Peter1977
User
Beiträge: 86
Registriert: Mittwoch 4. September 2013, 14:59

Hallo,
CREATE TABLE lg_lagerstand
(
id bigserial NOT NULL,
lagerplatz_id bigint,
artikel_id bigint,
menge numeric(5,0),
CONSTRAINT primary_lagerstand PRIMARY KEY (id),
CONSTRAINT fremd_artikel_id FOREIGN KEY (artikel_id)
REFERENCES lg_artikel (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fremd_lagerplatz_id FOREIGN KEY (lagerplatz_id)
REFERENCES lg_lagerplatz (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE lg_lagerstand
OWNER TO postgres;
Danke jetzt sollte es passen.

mfg Peter
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich hätte wohl bei der Benennung einige von den Präfixen weggelassen und auch die Constraints nicht gesondert benannt. Außerdem kann man sich die "ON UPDATE NO ACTION ON DELETE NO ACTION"-Zeilen auch sparen, da "NO ACTION" meines Wissens immer zur Anwendung kommt, wenn nichts anderes angegeben wird. Das alles würde die Datenbank-Definitionen etwas lesbarer machen.
Peter1977
User
Beiträge: 86
Registriert: Mittwoch 4. September 2013, 14:59

Hallo,

Ist Original aus pgAdmin3 herauskopiert.

Das man die Constraint Namen weglassen kann muss ich erst noch Testen.

nfg Peter
BlackJack

@Peter1977: So wie das da verwendet wird muss man AFAIK den Constraints Namen geben. snafu meinte die Constraints nicht extra hinten dran zu schreiben mit CONSTRAINT sondern schon bei der Deklaration der Spalte.
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich meinte es, wie hier gezeigt, grob nach diesem Schema:

Code: Alles auswählen

CREATE TABLE Orders
(
O_Id int NOT NULL PRIMARY KEY,
OrderNo int NOT NULL,
P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
)
Oder bei Kompatibilitätsproblemen so:

Code: Alles auswählen

CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
bb1898
User
Beiträge: 200
Registriert: Mittwoch 12. Juli 2006, 14:28

snafu hat geschrieben:Ich meinte es, wie hier gezeigt, grob nach diesem Schema:

Code: Alles auswählen

CREATE TABLE Orders
(
O_Id int NOT NULL PRIMARY KEY,
OrderNo int NOT NULL,
P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
)
Wie Peter1977 weiter oben schrieb, hat er die CREATE-Anweisung aus pgAdmin herauskopiert - und das stellt sie immer mit separaten und benannten Constraint-Definitionen dar, egal, wie man die Anweisung ursprünglich eingegeben hat. Die Namen werden ggf. automatisch vergeben.
Antworten