Hallo Leute
Habe folgendes Problem:
Ich versuche in einem SELECT Statement die Column Names variabel zu gestalten.
Nehmen wir an wir hätten eine Table "article" mit z.b. 2 columns "price_eur" und "price_usd".
Zudem habe ich eine Table "contact" mit der column "currency";
Ziel ist sowas wie:
So könnte ich den price in der jeweiligen Währung des angegebenen Kontakts bekommen ohne dass ich die Query jemals umbauen müsste.Code:SELECT 'price_' || (SELECT currency FROM contact WHERE id = 1) from article;
Leider bekomme ich dafür nur den string zurück, da Postgres so nicht weiss, das dieser string einen Spaltennamen repräsentiert. Quote ich die Begriffe jedoch nicht als string, kann ich sie nicht concatenaten.
Das Ergebnis ist also ungefähr so:
price_chf
price_chf
price_chf
price_chf
price_chf
price_chf
price_chf
Eine Idee von mir war, den string mit einem Cast als Column zu definieren. So was wie:
Leider kenne ich den korrekten Datentyp nicht, wenns überhaupt so einen gibt.Code:('price_' || 'eur')::column_name
Natürlich könnte ich das ganze auch mit plpgsql lösen, jedoch sehe ich nicht ein, weshalb man für so eine einfach query grad ne stored procedure bauen soll.
Hat irgendjemand eine Idee?![]()
Wenn Dein Modell normalisiert wäre und der Preis in einer Tabelle "price" mit einer Spalte "currency" gespeichert würde, dann hättest Du das ganze Problem nicht - dann wäre es nämlich ein einfacher Join.
Mit diesem Datenmodell geht es nicht anders.Natürlich könnte ich das ganze auch mit plpgsql lösen, jedoch sehe ich nicht ein, weshalb man für so eine einfach query grad ne stored procedure bauen soll.
Ein besseres Datenmodell!Hat irgendjemand eine Idee?![]()
A SQL query walks into a bar and sees two tables. He walks up to them and says 'Can I join you?'
Das geht nicht. Nicht mit SQL Das würde gehen mit z.B. plpgsql, aber auch dann nur als dynamisches Query, EXECUTE.
Der Grund ist simpel: Der Planner hat einen Plan zu erstellen. Das kann er nicht, wenn nicht schon vor Ausführung der Abfrage die Struktur des Ergebnisses feststehen würde.
In Kurz: vergiß es.
In Lang: überdenke Dein Design.
Andreas
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Merci für die Antworten.
Bezüglich Datenmodell: Ich hätte vielleicht vorwegnehmen sollen, dass mir bewusst ist, dass mein Datenmodell jeglicher Normalisierung widerspricht und sehr unschön ist. Leider gibt es gute Gründe für mich dies so zu tun. Meine Applikation hat mittlerweile Dimensionen angenommen, welche Änderungen in der Basis SEHR aufwändig machen. Ich habe mir das Design lange überlegt und auch die normalisierte Variante bereits als Diagramm skizziert. Ich hatte die Wahl zwischen der edlen, aufwändigen oder der einfachen, dafür etwas hässlichen (und mindestens um den Faktor 10 schnelleren) Lösung. Es ist lediglich eine Zeitfrage.
Ich bin bereits daran, eine dynamische Query mit EXECUTE zusammenzubasteln. Werde meine Lösung hier posten wenn ich fertig bin (ich hasse Problem-Threads ohne Lösung ^^).
Bezugnehmend auf deine Wahl zwischen Normalisierung oder nicht: nun stehst du vor dem Problem, Aufgaben lösen zu müssen, wie es in einer normalisierten Variante wohl nicht geben würde.
Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören
Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler
PostgreSQL Service & Support
Schwierig zu testen, dafür müsste ichs ja beinahe implementieren.Vermuteter Faktor 10, oder hast Du das wirklich getestet?
Der Faktor basiert auf Schätzungen, die ich anstellte, nachdem ich für beide Möglichkeiten Klassendigramme skizziert und die wichtigsten Relationen auch gleich als SQL Code implmentiert hatte.
Das Zusammenbauen der Relationen in SQL ist die eine Sache.....der grosse Aufwand entsteht dann erst beim Anpassen des php-Codes. Stell dir eine Informatikbude mit eigenem CMS (in php) und ca. 10'000 Kunden vor. Das gesamte Buchhaltungskonzept war ursprünglich für eine Währung vorgesehen (etwas kurzsichtig ... ich war auch nicht von Anfang an dabei). Änderungen in den fundamentalen Tabellen der Buchhaltung ziehen explosionsartigen Aufwand und Anpassungen des ganzen CMS nach sich. Mit anderen Worten: Mit der normalisierten Version müsste ich wirklich die gesamte Buchhaltung umbauen, da bliebe fast kein Stein auf dem anderen. Während diesen Umstellungen muss das Buchhaltungssystem auch noch nahtlos weiterfunktionieren.
Wir können mit grosser Sicherheit sagen, dass wir nie mehr Währungen als EUR, USD und GBP nutzen werden. Somit ist diese Sache langfristig geritzt. Ich möchte in Sachen Kurzsichtigkeit nicht die selben Fehler machen wie meine Vorgänger, aber ich denke, dass diese Lösung einen akzeptablen Kompromiss darstellt.
Mit der einfachen Version bin ich mit einigen Anpassungen über den Berg.
Das stimmt so wohl und war auch zu erwarten. Bisher ist dies jedoch das einzige Problem, das sich mit dieser Variante stellt und es sieht nach einem in Kauf zu nehmenden Aufwand aus.Bezugnehmend auf deine Wahl zwischen Normalisierung oder nicht: nun stehst du vor dem Problem, Aufgaben lösen zu müssen, wie es in einer normalisierten Variante wohl nicht geben würde.
Geändert von luba (25.05.2010 um 11:31 Uhr)
So.
Hier wäre mal meine Lösung. Wem's zu dirty ist: Bitte die Augen zuhalten.
Nun kannn ich also mit einem einfachenCode:CREATE FUNCTION get_article_price_by_contact(i_article_id integer, i_contact_id integer) RETURNS numeric AS $$ DECLARE price numeric; currency_code varchar; BEGIN currency_code := (SELECT code FROM currency WHERE id = (SELECT currency_id FROM contact WHERE id = i_contact_id)); EXECUTE 'SELECT price_' || currency_code || ' FROM article WHERE id = ' || i_article_id INTO price; RETURN price; END; $$ LANGUAGE plpgsql;
gemütlich den jeweiligen Preis in der richtigen Währung holen.Code:SELECT get_article_price_by_contact(1,1);
Für mich ist das Problem zufriedenstellend gelöst. Danke für die Diskussion.
Dafür hat man Entwickler-, Test-, Staging- und Produktivsysteme.
Auf einem Livesystem entwickelt man nicht. Niemals.
Warten wir, bis der EUR an Wert verliert und die Chinesem mit den CNY oder die Russen mit dem RUB eine Rolle spielen.Wir können mit grosser Sicherheit sagen, dass wir nie mehr Währungen als EUR, USD und GBP nutzen werden.
Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören
Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler
PostgreSQL Service & Support
Kann ich nur zustimmen. Trotzdem zeigt die Praxis, dass man auch mit dem besten Unit-Testing selten alle Fälle abdecken kann und leider unterscheiden sich Testumgebungen oft leicht von Livesystemen.
Wir sprechen hier davon, das Herzstück unseres CMS auszutauschen. Das wird definitiv nicht einfach über die Bühne gehen.
Na gut - stattgegeben ^^. Aber diese Erweiterungen wären danach Peanuts.Warten wir, bis der EUR an Wert verliert und die Chinesem mit den CNY oder die Russen mit dem RUB eine Rolle spielen.
Links: Tobias Bauer - IT- und Funkdienstleistungen - Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen - Funkforum
Lesezeichen