Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Select Abfrage mit 2 von-bis Angaben

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Select Abfrage mit 2 von-bis Angaben

    Hallo,

    ich habe mir eine Datenbank erstellt. In dieser gibt es 2 Tabellen.
    Eine für den gelben Bereich (s. Bild) und eine für den grünen Bereich. Beide sind mit einer von und bis Spalte belegt. Die 3 Tabelle sind die ausgelagerten Zahlen (z.B. blaues Feld) und eine Zwischentabelle wo die IDs gespeichert sind.

    Zur Erklärung. Ich möchte 2 Eingabefelder mit den Bezeichnungen strom und öl haben, wo die eingegeben Daten an PHP übergeben werden. strom soll die gelbe Zeile abfragen und öl die grüne Spalte. Sind beide Werte gefunden soll eine Verbindung (blaues Feld) entstehen. Also wie eine x-y Verbindung in Mathe.

    Dieser Wert soll ausgegeben werden.

    Ich habe es schon mit folgender Select Abfrage versucht, aber da gibt er mir leider alle Werte mehrmals untereinander aus.

    Code:
    $result = mysql_query("Select zahlen From kosten, zwischentabelle, id_oel, id_strom Where '$strom' Between id_strom.stromvon and id_strom.strombis and '$oel' between id_oel.oelvon and id_oel.oelbis");
    
    while($row = mysql_fetch_row($result))
    echo $row[0].'<br />';
    Hat jemand zufällig eine Verbesserungsmöglichkeit oder sollte ich es besser mit Switch Case in PHP hardgecodet machen?
    Angehängte Dateien

  • #2
    Das Problem ist, du weißt nicht, in welcher (grüner) Spalte das Ergebnis liegt. Wenn du aber SELECT * ... machst, bekommst du zwar die richtige Zeile, aber eben alle Zahlen der Zeile. Überarbeite dein Tabellendesign nochmal.

    Und bitte verwende mysqli_query($connection, ""); und mysqli_fetch_row($result);

    Kommentar


    • #3
      Ja das ist es ebend. Er müsste die Spanne erkennen in welcher die Zahl liegt. Das blaue sollte nur ein Beispiel sein, um es anschaulicher zu machen.

      Kommentar


      • #4
        drei tabellen in eine gepackt, hut ab.
        was ist aus dem andren thread geworden, auf erledigt klicken oder so?

        Kommentar


        • #5
          Erledigt habe ich eben geklickt. Naja was soll ich sonst machen, Vorgabe des Kunden. Nun muss ich versuchen das irgendwie in eine Abfrage zu packen oder per Switch Case hardgecodet (diese Funktion funktioniert, aber ist eben nicht besonders elegant gelöst).

          Kommentar


          • #6
            Was speicherst du wie und wo in der Datenbank?

            Kommentar


            • #7
              in der Datenbank werden folgende Daten gespeichert.

              Tabelle Strom:
              VonStrom
              BisStrom
              Strom_ID

              Tabelle Oel:
              VonOel
              BisOel
              Oel_ID

              Tabelle Gewinn:
              Zahlen
              Zahlen_ID

              Tabelle Zwischentabelle:
              Zwischentabelle_ID
              Zahlen_ID
              Strom_ID
              Oel_ID

              Kommentar


              • #8
                Zitat von ladyragna Beitrag anzeigen
                in der Datenbank werden folgende Daten gespeichert.

                Tabelle Strom:
                VonStrom
                BisStrom
                Strom_ID

                Tabelle Oel:
                VonOel
                BisOel
                Oel_ID

                Tabelle Gewinn:
                Zahlen
                Zahlen_ID

                Tabelle Zwischentabelle:
                Zwischentabelle_ID
                Zahlen_ID
                Strom_ID
                Oel_ID

                Ich versuch das mal nachzubauen:

                Code:
                test=*# \d strom
                         Table "public.strom"
                    Column     |   Type    | Modifiers 
                ---------------+-----------+-----------
                 strom_id      | integer   | not null
                 strom_von_bis | int4range |
                Indexes:
                    "strom_pkey" PRIMARY KEY, btree (strom_id)
                Referenced by:
                    TABLE "zwischentabelle" CONSTRAINT "zwischentabelle_strom_id_fkey" FOREIGN KEY (strom_id) REFERENCES strom(strom_id)
                
                test=*# \d oel
                         Table "public.oel"
                   Column    |   Type    | Modifiers
                -------------+-----------+-----------
                 oel_id      | integer   | not null
                 oel_von_bis | int4range |
                Indexes:
                    "oel_pkey" PRIMARY KEY, btree (oel_id)
                Referenced by:
                    TABLE "zwischentabelle" CONSTRAINT "zwischentabelle_oel_id_fkey" FOREIGN KEY (oel_id) REFERENCES oel(oel_id)
                
                test=*# \d gewinn
                      Table "public.gewinn"
                  Column   |  Type   | Modifiers
                -----------+---------+-----------
                 zahlen_id | integer | not null
                 zahlen    | integer |
                Indexes:
                    "gewinn_pkey" PRIMARY KEY, btree (zahlen_id)
                Referenced by:
                    TABLE "zwischentabelle" CONSTRAINT "zwischentabelle_zahlen_id_fkey" FOREIGN KEY (zahlen_id) REFERENCES gewinn(zahlen_id)
                
                test=*# \d zwischentabelle
                 Table "public.zwischentabelle"
                  Column   |  Type   | Modifiers
                -----------+---------+-----------
                 id        | integer | not null
                 zahlen_id | integer |
                 strom_id  | integer |
                 oel_id    | integer |
                Indexes:
                    "zwischentabelle_pkey" PRIMARY KEY, btree (id)
                Foreign-key constraints:
                    "zwischentabelle_oel_id_fkey" FOREIGN KEY (oel_id) REFERENCES oel(oel_id)
                    "zwischentabelle_strom_id_fkey" FOREIGN KEY (strom_id) REFERENCES strom(strom_id)
                    "zwischentabelle_zahlen_id_fkey" FOREIGN KEY (zahlen_id) REFERENCES gewinn(zahlen_id)
                
                test=*#
                Mit diesen Werten:

                Code:
                test=*# select * from strom;
                 strom_id | strom_von_bis
                ----------+---------------
                        1 | [0,10)
                        2 | [10,20)
                        3 | [20,30)
                (3 rows)
                
                Time: 0,161 ms
                test=*# select * from oel;
                 oel_id | oel_von_bis
                --------+-------------
                      1 | [0,10)
                      2 | [10,20)
                      3 | [20,30)
                (3 rows)
                
                Time: 0,165 ms
                test=*# select * from gewinn ;
                 zahlen_id | zahlen
                -----------+--------
                         1 |     10
                         2 |     12
                         3 |     14
                         4 |     16
                (4 rows)
                
                Time: 0,161 ms
                test=*# select * from zwischentabelle ;
                 id | zahlen_id | strom_id | oel_id
                ----+-----------+----------+--------
                  1 |         1 |        1 |      1
                  2 |         2 |        1 |      2
                  3 |         2 |        2 |      1
                  4 |         3 |        2 |      2
                  5 |         3 |        1 |      3
                  6 |         3 |        3 |      1
                (6 rows)
                Was ist zu zahlen bei Strom = 5 und Öl = 22?

                Code:
                test=*# select zahlen from gewinn g left join zwischentabelle z on g.zahlen_id=z.zahlen_id left join oel o on z.oel_id=o.oel_id left join strom s on z.strom_id=s.strom_id where s.strom_von_bis @>5 and o.oel_von_bis @> 22;
                 zahlen
                --------
                     14
                (1 row)
                Einfach, oder?

                Auf Indexe hab ich mal verzichtet, aber um es kurz zu zeigen. Da sollten nun GiST-Indexe verwendet werden, damit der @> - Operator davon profitiert:

                Code:
                test=*# create index strom_werte on strom using gist (strom_von_bis);
                CREATE INDEX                                                         
                Time: 1,252 ms                                                       
                test=*# create index oel_werte on oel using gist (oel_von_bis);
                CREATE INDEX                                                   
                Time: 0,791 ms
                test=*# explain select zahlen from gewinn g left join zwischentabelle z on g.zahlen_id=z.zahlen_id left join oel o on z.oel_id=o.oel_id left join strom s on z.strom_id=s.strom_id where s.strom_von_bis @>5 and o.oel_von_bis @> 22;
                                                       QUERY PLAN
                ----------------------------------------------------------------------------------------
                 Nested Loop  (cost=1.21..36.84 rows=1 width=4)
                   ->  Nested Loop  (cost=1.05..36.63 rows=1 width=4)
                         Join Filter: (z.strom_id = s.strom_id)
                         ->  Seq Scan on strom s  (cost=0.00..1.04 rows=1 width=4)
                               Filter: (strom_von_bis @> 5)
                         ->  Hash Join  (cost=1.05..35.48 rows=9 width=8)
                               Hash Cond: (z.oel_id = o.oel_id)
                               ->  Seq Scan on zwischentabelle z  (cost=0.00..27.70 rows=1770 width=12)
                               ->  Hash  (cost=1.04..1.04 rows=1 width=4)
                                     ->  Seq Scan on oel o  (cost=0.00..1.04 rows=1 width=4)
                                           Filter: (oel_von_bis @> 22)
                   ->  Index Scan using gewinn_pkey on gewinn g  (cost=0.15..0.20 rows=1 width=8)
                         Index Cond: (zahlen_id = z.zahlen_id)
                (13 rows)
                
                Time: 0,933 ms
                test=*# set enable_seqscan to off;
                SET
                Time: 0,053 ms
                test=*# explain select zahlen from gewinn g left join zwischentabelle z on g.zahlen_id=z.zahlen_id left join oel o on z.oel_id=o.oel_id left join strom s on z.strom_id=s.strom_id where s.strom_von_bis @>5 and o.oel_von_bis @> 22;
                                                                QUERY PLAN
                -----------------------------------------------------------------------------------------------------------
                 Nested Loop  (cost=10000000008.44..10000000044.32 rows=1 width=4)
                   ->  Nested Loop  (cost=10000000008.29..10000000044.11 rows=1 width=4)
                         ->  Hash Join  (cost=10000000008.16..10000000042.59 rows=9 width=8)
                               Hash Cond: (z.oel_id = o.oel_id)
                               ->  Seq Scan on zwischentabelle z  (cost=10000000000.00..10000000027.70 rows=1770 width=12)
                               ->  Hash  (cost=8.15..8.15 rows=1 width=4)
                                     ->  Index Scan using oel_werte on oel o  (cost=0.13..8.15 rows=1 width=4)
                                           Index Cond: (oel_von_bis @> 22)
                         ->  Index Scan using strom_pkey on strom s  (cost=0.13..0.16 rows=1 width=4)
                               Index Cond: (strom_id = z.strom_id)
                               Filter: (strom_von_bis @> 5)
                   ->  Index Scan using gewinn_pkey on gewinn g  (cost=0.15..0.20 rows=1 width=8)
                         Index Cond: (zahlen_id = z.zahlen_id)
                (13 rows)
                
                Time: 0,738 ms
                Mußte seq_scan auf off setzen, weil zu wenig Datensätze in den Tabellen sind. Da fehlen natürlich noch weitere Indexe:

                Code:
                test=*# create index z_zahlen on zwischentabelle (zahlen_id);
                CREATE INDEX
                Time: 7,457 ms
                test=*# create index z_strom on zwischentabelle (strom_id);
                CREATE INDEX
                Time: 2,458 ms
                test=*# create index z_oel on zwischentabelle (oel_id);
                CREATE INDEX
                Time: 1,368 ms
                test=*# explain select zahlen from gewinn g left join zwischentabelle z on g.zahlen_id=z.zahlen_id left join oel o on z.oel_id=o.oel_id left join strom s on z.strom_id=s.strom_id where s.strom_von_bis @>5 and o.oel_von_bis @> 22;
                                                            QUERY PLAN
                --------------------------------------------------------------------------------------------------
                 Nested Loop  (cost=0.55..23.32 rows=1 width=4)
                   ->  Nested Loop  (cost=0.42..21.16 rows=1 width=8)
                         ->  Nested Loop  (cost=0.26..16.31 rows=1 width=8)
                               ->  Index Scan using oel_werte on oel o  (cost=0.13..8.15 rows=1 width=4)
                                     Index Cond: (oel_von_bis @> 22)
                               ->  Index Scan using z_oel on zwischentabelle z  (cost=0.13..8.15 rows=1 width=12)
                                     Index Cond: (oel_id = o.oel_id)
                         ->  Index Scan using gewinn_pkey on gewinn g  (cost=0.15..4.84 rows=1 width=8)
                               Index Cond: (zahlen_id = z.zahlen_id)
                   ->  Index Scan using strom_pkey on strom s  (cost=0.13..2.15 rows=1 width=4)
                         Index Cond: (strom_id = z.strom_id)
                         Filter: (strom_von_bis @> 5)
                (12 rows)
                PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                Kommentar


                • #9
                  Zitat von ladyragna Beitrag anzeigen
                  in der Datenbank werden folgende Daten gespeichert.
                  Der Aufbau ist ein wenig fragwürdig, aber lassen wir das mal so stehen. Prinzipiell ist dein Query aber richtig. Der Fehler ist du hast keine Join-Bedingungen angegeben, damit erzeugst du ein Kreuzprodukt zwischen alle Datensätzen der Tabellen.

                  http://de.wikibooks.org/wiki/Einf%C3...eiten_mit_JOIN

                  PHP-Code:
                  FROM
                    zwischentabelle INNER JOIN
                    id_oel ON 
                  (zwischentabelle.oel_id id_oel.oel_idINNER JOIN
                    id_strom ON 
                  (zwischentabelle.strom_id = ...) INNER JOIN
                    zahlen ON 
                  (...) 

                  Kommentar


                  • #10
                    danke akretschmer für die ausführlicheren erklärungen.
                    sonst kann ich nur auf den anderen thread verweisen, TE.

                    Kommentar


                    • #11
                      Zitat von moma Beitrag anzeigen
                      danke akretschmer für die ausführlicheren erklärungen.
                      gerne doch
                      PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                      Kommentar


                      • #12
                        Zitat von erc Beitrag anzeigen
                        Der Aufbau ist ein wenig fragwürdig, aber lassen wir das mal so stehen. Prinzipiell ist dein Query aber richtig. Der Fehler ist du hast keine Join-Bedingungen angegeben, damit erzeugst du ein Kreuzprodukt zwischen alle Datensätzen der Tabellen.
                        Das war so gedacht, dass keine doppelt vorhandenen Werte in den Tabellen vorhanden sind. Also wenn ihr da andere Vorschläge habt, bin ich gern bereit mich eines besseren belehren zu lassen.

                        Kommentar


                        • #13
                          Zitat von ladyragna Beitrag anzeigen
                          Das war so gedacht, dass keine doppelt vorhandenen Werte in den Tabellen vorhanden sind.
                          Dazu verwendet man passende Indexe. Ob Du solche hast ist nicht erkennbar.
                          PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                          Kommentar


                          • #14
                            Zitat von akretschmer Beitrag anzeigen
                            Dazu verwendet man passende Indexe. Ob Du solche hast ist nicht erkennbar.
                            Nachtrag: Es ist auch nicht erkennbar, ob Du sich überlappende Werte in Deinen von-bis - Spalten verhinderst. Das dürfte mit MySQL schwer bis unmöglich sein. Wäre ja mal interessant, ob Du das realisiert hast, und wenn ja, wie.
                            PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                            Kommentar


                            • #15
                              Passende Indexe????

                              Kommentar

                              Lädt...
                              X