Virtuele Tabelle mit where Klausis

Huhu,

kann ich in Postgres (wahrschienlich mit partman) eine Tabelle anlegen, wo alle Daten anhand einer komplizieren where enthalten sind?

z.B.:
ich habe die TABELE
table(id, Name text, Alter INT)
und möchte jetzt die eine table_Familie, mit folgender Klausis
select * from table WHERE ("Name" ILIKE "Rothshild" OR "Name" ILIKE "Warburg" OR "Name" ILIKE "Rabiner" ....) AND Alter > 50;

partition by list, ja, das kann PostgreSQL. Aber: das Alter ist keine Konstante, das ändert sich bei den meisten Menschen ca. 1 mal pro Jahr. Danach kannst Du nicht partitionieren. Du kannst aber nach Geburtsjahr partitionieren - das ändert sich üblicherweise kaum …

Du suchst m.E. keine Tabelle sondern eine View, außerdem ist wie der Vorposter schon anmerkte die Spalte “Alter” wahrscheinlich eine eher schlechte Idee.

Ein ILIKE-Kriterium läuft immer große Gefahr, zu einem Table Scan zu werden. Deshalb wäre evtl. ein funktionaler Index über eine normalisierte Form des Namensm der eine Suche über IN oder = erlaubt, besser. NAME ist ein gefährlicher Spaltenname weil in vielen Programmiersprachen ein reserviertes Wort, ALTER ist ein reserviertes Wort in SQL und daher auch keine so gute Idee.

Semantisch würde ich in dem Fall eher VARCHAR als TEXT für das Namensfeld nehmen. In Postgresql sind beide zwar äquivalent, in anderen RDBMS steht TEXT jedoch meist für ein CLOB, VARCHAR für ein einfaches variables Textfeld mit deutlicher Längenbegrenzung (250, 2000 oder auch 65000 Zeichen je nach RDBMS). Daß ein Name diese Grenze reißt ist sehr unwahrscheinlich. und LOBs sind in manchen RDBMS sehr eingeschränkt und unperformant. Nimmt man nur wenn es dafür gute Gründe gibt.

Meine Lösung wäre deshalb ungefähr (untested):

CREATE TABLE DATEN (
       ID INTEGER PRIMARY KEY, 
       NACHNAME CHARACTER VARYING, 
       GEBURTSJAHR INTEGER
);

CREATE INDEX I01 ON DATEN (UPPER(TRIM(NACHNAME))), GEBURTSJAHR;

CREATE VIEW FAMILIE AS
SELECT * 
  FROM DATEN
 WHERE UPPER(TRIM(NACHNAME)) 
       IN ('ROTHSCHILD', 'WARBURG','RABINER')
   AND GEBURTSJAHR < 
       (EXTRACT(YEAR FROM CURRENT_TIMESTAMP) + 50)

(Korrektur 21.05 22:00 Uhr: Primärschlüssel ergänzt, Syntax von EXTRACT korrigiert)

Du kannst anstatt einer View prinzipiell auch eine Tabelle anlegen, aber dann mußt Du jede Datensatzänderung in DATEN in der Tabelle nachpflegen, das ist normalerweise grober Unfug. Sollte es Performanceprobleme geben, würde ich mir zuerst Struktur, Kriterien und Indices anschauen und nur wenn da nichts zu holen ist wäre eine indizierte oder materialisierte View die nächstbeste Option. Eine separate Tabelle eigentlich nur dann, wenn deren Inhalt Änderungen der Basisdaten bewußt nicht mitmachen soll (z.B. als Archiv).

Diskutieren kann man auch, ob man das Geburtsjahr oder den Geburtstag (dann als DATE) speichert. Dann muß natürlich die Bedingung entsprechend angepaßt werden. Für viele Anwendungszwecke reicht das Geburtsjahr völlig aus und ist dann oft die sehr viel einfachere Lösung, aber wenn das Datenmodell universell bleiben soll würde ich zumindest in der Basistabelle das Geburtsdatum nehmen. Man könnte auch das Geburtsjahr implizit in der View ermitteln.

1 „Gefällt mir“