Ergebnis 1 bis 8 von 8

Thema: Alternative zu Mehrfach join einer Tabelle

  1. #1
    mkuis ist offline Benutzer
    Registriert seit
    20.08.2009
    Ort
    Bonn
    Beiträge
    50

    Unglücklich Alternative zu Mehrfach join einer Tabelle

    Hallo,
    ich möchte zu einer Stammtabelle aller Nutzungen nebeneinander sehen. Gibt es eine eleganter Methode, als die Untertabelle xmal zu joinen??

    Ich habe drei Tabellen:

    • eine Haupttabelle stamm

    CREATE TABLE stamm
    (
    lfd_nr integer NOT NULL,
    name character varying(10),
    ....
    CONSTRAINT verwal_pkey PRIMARY KEY (lfd_nr))
    • Eine Nutzungs-Typen-Tabelle

    CREATE TABLE nutzung_typ(
    nutzung smallint NOT NULL,
    bezeichnung character(50),
    CONSTRAINT nutz_typ_pkey PRIMARY KEY (nr)
    )

    • sowie eine Tabelle der verwandeten Nutzungen

    CREATE TABLE nutzung
    (
    lfd_nr integer NOT NULL,
    nutzung smallint NOT NULL,
    menge integer,
    CONSTRAINT nutzung_pkey PRIMARY KEY (lfd_nr, nutzung),
    CONSTRAINT verwal FOREIGN KEY (lfd_nr)
    REFERENCES stamm(lfd_nr) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT verwal FOREIGN KEY (nutzung )
    REFERENCES nutzung_typ (nutzung ) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
    )


    Herauskommen soll:
    lfd_nr (menge aus Nutzung1) (menge aus Nutzung2)
    (menge aus Nutzung3) ...
    für alle möglichen Nutzungen aus der Tabelle nutzung_typ, auch für die, die nicht in der Tabelle nutzung verwandt worden.

    Ich könnte zwar mit dem SQL
    select lfd_nr, name
    , n1.menge as menge1, n2.menge as menge2, n3.menge as menge3
    from stamm s
    left join nutzung n1 on s.lfd_nr = n1.
    lfd_nr and nutzung = 1
    left join nutzung n2 on s.lfd_nr = n2.lfd_nr and nutzung = 2
    left join nutzung n3 on s.lfd_nr = n3.lfd_nr and nutzung = 3

    arbeiten, aber ich habe 30 Nutzungen und finde das nicht so toll.


    Kennt jemand eine Lösung???

  2. #2
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von mkuis Beitrag anzeigen
    Hallo,
    ich möchte zu einer Stammtabelle aller Nutzungen nebeneinander sehen. Gibt es eine eleganter Methode, als die Untertabelle xmal zu joinen??

    Ich habe drei Tabellen:

    • eine Haupttabelle stamm

    CREATE TABLE stamm
    (
    lfd_nr integer NOT NULL,
    name character varying(10),
    ....
    CONSTRAINT verwal_pkey PRIMARY KEY (lfd_nr))
    • Eine Nutzungs-Typen-Tabelle

    CREATE TABLE nutzung_typ(
    nutzung smallint NOT NULL,
    bezeichnung character(50),
    CONSTRAINT nutz_typ_pkey PRIMARY KEY (nr)
    )

    • sowie eine Tabelle der verwandeten Nutzungen

    CREATE TABLE nutzung
    (
    lfd_nr integer NOT NULL,
    nutzung smallint NOT NULL,
    menge integer,
    CONSTRAINT nutzung_pkey PRIMARY KEY (lfd_nr, nutzung),
    CONSTRAINT verwal FOREIGN KEY (lfd_nr)
    REFERENCES stamm(lfd_nr) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT verwal FOREIGN KEY (nutzung )
    REFERENCES nutzung_typ (nutzung ) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
    )


    Herauskommen soll:
    lfd_nr (menge aus Nutzung1) (menge aus Nutzung2)
    (menge aus Nutzung3) ...
    für alle möglichen Nutzungen aus der Tabelle nutzung_typ, auch für die, die nicht in der Tabelle nutzung verwandt worden.

    Ich könnte zwar mit dem SQL
    select lfd_nr, name
    , n1.menge as menge1, n2.menge as menge2, n3.menge as menge3
    from stamm s
    left join nutzung n1 on s.lfd_nr = n1.
    lfd_nr and nutzung = 1
    left join nutzung n2 on s.lfd_nr = n2.lfd_nr and nutzung = 2
    left join nutzung n3 on s.lfd_nr = n3.lfd_nr and nutzung = 3

    arbeiten, aber ich habe 30 Nutzungen und finde das nicht so toll.


    Kennt jemand eine Lösung???
    Müssen das einzelne Spalten sein? Geht das auch in Reihen?

    Code:
    test=*# select * from stamm ;
     lfd_nr |  name
    --------+--------
          1 | stamm1
          2 | stamm2
    (2 rows)
    
    test=*# select * from nutzung ;
     lfd_nr | nutzung | menge
    --------+---------+-------
          1 |       1 |    10
          1 |       2 |    20
          1 |       3 |    30
          1 |       4 |    40
          1 |       1 |    11
          1 |       2 |    21
          1 |       3 |    31
    (7 rows)
    
    test=*# select s.lfd_nr, n.nutzung, sum(n.menge) from stamm s left join nutzung n using(lfd_nr) group by lfd_nr, nutzung;
     lfd_nr | nutzung | sum
    --------+---------+-----
          1 |       4 |  40
          1 |       3 |  61
          1 |       2 |  41
          1 |       1 |  21
          2 |         |
    (5 rows)
    Falls Du das wirklich nebenander haben willst: das skaliert schlecht, wenn eine neue Nutzungsart dazu kommt, hast Du Dein SQL umzubauen.
    Du könntest ein contrib-Modul nehmen, tablefunc. Dies enthält eine CROSSTAB-Funktion. Und dann hab ich noch diesen Link:

    Pavel Stehule's blog: Using cursors for generating cross tables


    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  3. #3
    mkuis ist offline Benutzer
    Registriert seit
    20.08.2009
    Ort
    Bonn
    Beiträge
    50

    Standard

    Danke für die Antwort.

    Ich brauche es unbedingt in Zeilen, das und das es nicht skalierbar ist, ist ja mein Problem.

    Ich schau mir die Erweiterung mal an...

  4. #4
    mkuis ist offline Benutzer
    Registriert seit
    20.08.2009
    Ort
    Bonn
    Beiträge
    50

    Standard

    hat super geholfen. Danke nochmal

  5. #5
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von mkuis Beitrag anzeigen
    hat super geholfen. Danke nochmal
    Wenn Du jetzt noch mal zeigen und erklären würdest, was Du gemacht hast, wäre vielleicht sogar auch noch anderen geholfen.


    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  6. #6
    mkuis ist offline Benutzer
    Registriert seit
    20.08.2009
    Ort
    Bonn
    Beiträge
    50

    Standard

    Ich wollte mich nicht mit fremden Federn schücken.

    Ich habe die (nicht von mir stammende) Funktion nachgebildet:
    CREATE OR REPLACE FUNCTION do_cross_cursor(dimx_name character varying, dimx_source character varying, dimy_name character varying, dimy_source character varying, expr character varying)
    RETURNS refcursor AS
    $BODY$
    DECLARE
    col_list text[] := '{}';
    query text;
    r RECORD;
    result refcursor := 'result';
    BEGIN
    FOR r IN EXECUTE 'SELECT DISTINCT '
    || dimx_name || '::text AS val ' || dimx_source
    LOOP
    col_list := array_append(col_list, 'SUM(CASE ' || dimx_name
    || ' WHEN ' || quote_literal(r.val) || ' THEN ' || expr
    || ' ELSE 0 END) AS ' || quote_ident(r.val) || '');
    END LOOP;
    query := 'SELECT ' || dimy_name || ', '
    || array_to_string(col_list, ',')
    || ', SUM(' || expr || ') AS Total '
    || dimy_source || ' GROUP BY ' || dimy_name;
    OPEN result NO SCROLL FOR EXECUTE query;
    RETURN result;
    END;
    $BODY$
    LANGUAGE 'plpgsql' VOLATILE STRICT
    COST 100;

    Damit kann man das Problem dann ganz einfach lösen mit:

    SELECT * from do_cross_cursor('bezeichnung', 'FROM nutzung_typ','lfd_nr',
    'FROM nutzung e JOIN nutzung_typ s using(nutzung)',
    'menge');
    FETCH ALL FROM result;

  7. #7
    mkuis ist offline Benutzer
    Registriert seit
    20.08.2009
    Ort
    Bonn
    Beiträge
    50

    Standard

    ich habe noch eine letzte Frage:

    wie kann ich das Ganze in einem SQL nutzen, ohne den Fetch all???

  8. #8
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von mkuis Beitrag anzeigen
    ich habe noch eine letzte Frage:

    wie kann ich das Ganze in einem SQL nutzen, ohne den Fetch all???
    Die Funktion liefert einen CURSOR, insofern wirst Du wohl damit leben müssen, die Daten via FETCH zu holen. Du kannst ja versuchen, das alles in einer Funktion nochmals zu kapseln.

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

Ähnliche Themen

  1. Update einer Tabelle nach Join
    Von Reptil im Forum SQL
    Antworten: 2
    Letzter Beitrag: 10.08.2011, 08:48
  2. Antworten: 4
    Letzter Beitrag: 01.03.2011, 12:05
  3. Problem mit Mehrfach Join
    Von hafi im Forum SQL
    Antworten: 4
    Letzter Beitrag: 19.02.2008, 09:48
  4. Antworten: 4
    Letzter Beitrag: 05.10.2007, 12:17
  5. Antworten: 2
    Letzter Beitrag: 19.09.2007, 16:57

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Links: Tobias Bauer - IT- und Funkdienstleistungen   -   Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen   -   Funkforum