Superheld: MYSQL Abfrage über 366 Felder

Hallo zusammen,

ich hänge gerade ein wenig und suche nach einem guten Tipp.
Ich habe eine Tabelle mit 366 Feldern (varchar, jedes feld beginnt mit dem Unterstrich "_", z.B. "_22_10".
Nun möchte ich "eigentlich" nur abfragen ob eines dieser 366 Felder nicht leer ist.

Aber ein query mit 366 Feldern kommt mir etwas "viel" vor.
Hat jemand eine andere Lösung/Idee?

Viele Grüsse

  1. Hallo,

    ich hänge gerade ein wenig und suche nach einem guten Tipp.
    Ich habe eine Tabelle mit 366 Feldern (varchar, jedes feld beginnt mit dem Unterstrich "_", z.B. "_22_10".

    das sieht danach aus, als hättest Du für jeden Tag des Kalenderjahres eine Spalte.

    Aber ein query mit 366 Feldern kommt mir etwas "viel" vor.
    Hat jemand eine andere Lösung/Idee?

    Verwende ein sinnvolleres Tabellendesign und trage den Tag in eine Datumsspalte ein.

    Ja, ich weiß, daraus eine Übersicht zu machen, die für jeden Tag eine Spalte hat, ist in MySQL nicht trivial (und überlässt man der API).

    Freundliche Grüße

    Vinzenz

    1. Hallo,

      fast richtig. Es wird aber kein Datum eingetragen sondern nur der Wert 0 oder 1.
      Wie kann ich die id der Zeile abfragen, in der mindestens eines der Felder _01_01 bis _31_12 nicht ller ist bzw. den Wert 1 hat?

      Viele Grüsse

      1. Hallo,

        fast richtig. Es wird aber kein Datum eingetragen sondern nur der Wert 0 oder 1.
        Wie kann ich die id der Zeile abfragen, in der mindestens eines der Felder _01_01 bis _31_12 nicht ller ist bzw. den Wert 1 hat?

        Genau das hat Vinzenz doch erraten.

        Dein Tabellen-Design ist Mist!
        1. Ist fraglich warum du "varchar" verwendest obwohl du nur drei Zustände brauchst, nämlich "1", "0" und leer.
        2. Entweder du willst nur einen bestimmten Tag speichern für den die Zeile zutrifft, also in allen 366 Spalten kommt genau eine 1 und sonst nur 0en und leere Werte vor, dann eignet sich eine einzelne Datums-Spalte in der Tabelle.
        oder aber du willst mehrere zutreffende Tage speichern, dann eignet sich eine zweite Tabelle, in der du zeilenweise die Relation Datensatz=>Datum anlegst und diese dann dynamisch einlinkst.

        --
        sh:( fo:| ch:? rl:( br:& n4:& ie:{ mo:} va:) de:µ_de:] zu:) fl:( ss:| ls:[ js:(
        1. Hallo,

          warum kann man nicht einfach meine Frage beantworten als mir etwas zu empfehlen was ich nicht brauchen kann?

          Ich brauche sowas in der Richtung:

            
          mysql_query("SELECT id FROM `tabelle` WHERE _01_01 bis _31_12 != ''");  
          
          

          oder

            
          mysql_query("SELECT id FROM `tabelle` WHERE feld beginnt mit "_" != ''");  
          
          

          Freue mich über eine Antwort auf meine Frage.

          1. Mahlzeit Superheld,

            warum kann man nicht einfach meine Frage beantworten als mir etwas zu empfehlen was ich nicht brauchen kann?

            Weil Dir das auf Dauer nicht weiterhilft! Außerdem gilt immer noch Zitat 224 ... und wenn ein Tabellendesign nun einmal Mist ist, dann wird das hier eben auch erwähnt. Akzeptiere das.

            Ich brauche sowas in der Richtung:

            mysql_query("SELECT id FROM tabelle WHERE _01_01 bis _31_12 != ''");

            
            >   
            > oder  
            >   
            > ~~~php
              
            
            > mysql_query("SELECT id FROM `tabelle` WHERE feld beginnt mit "_" != ''");  
            > 
            
            

            So etwas gibt es aber nicht. Und selbst wenn es so etwas gäbe, wäre es höchstwahrscheinlich extrem inperformant und es wäre in jedem Fall ratsam, das Tabellendesign zu korrigieren.

            Freue mich über eine Antwort auf meine Frage.

            Die hast Du bereits erhalten.

            MfG,
            EKKi

            --
            sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
            1. Hallo,

              warum ist das Tabellendesign mist? Die Felder sind varchar(10) weil dort in der Zukunft nicht nur Zahlen sonder "Kürzel" eingetragen werden.
              Die Feldnamen sind eindeutig und sehr sinnig benannt.

              Vielen Dank für eure Tipps

              1. Hi there,

                warum ist das Tabellendesign mist?

                Weil das Speichern von ein paar Hundert Einträgen in genau EINER Zeile dem Konzept relationaler Datenbanken diametral entgegenläuft.

                Die Felder sind varchar(10) weil dort in der Zukunft nicht nur Zahlen sonder "Kürzel" eingetragen werden.

                Ja, ok, trotzdem wäre es besser, einfach eine Tabelle zu nehmen, die 366 Zeilen und EIN Feld hat, das dann von mir aus Varchar 10 oder irgendetwas sein kann. Zugriff auf den Inhalt hast Du dann über den Record, der einfach ein Wert zwischen 1 und 366 sein kann. Das geht in dem Fall fast genauso schnell wie das Herausklauben eines Wertes aus 366 (horizontalen) Feldern...

                1. Nochmal Hallo,

                  vielen Dank für die Antworten (auch deine letzte Vinzenz).
                  Jetzt verstehe ich langsam was Ihr meint-kann es aber noch nicht umsetzen.

                  Ich versuche mal zu erläutern was ich vorhabe:

                  Es gibt eine Tabelle mit mehreren 1000 Usern.
                  Nun hat jeder User auch eine Tabelle mit den besagten 366 Spalten für jeden Tag des Jahres. Jeder User kann mehrer Tage markieren wann er online ist-aber nur innerhalb der jeweils nöchsten 2 Monate.

                  Daher war die Idee das in meine (schlechte) Tabelle die Kürzel des User am entsprechenden Tag eingetragen werden.

                  Dann wollte ich abfragen welcher User überhaupt einen Eintrag hat und dies weiter verarbeiten...

                  1. Hallo,

                    in Verbindung mit den anderen Tipps, die du schon bekommen hast, kommt dann also raus, dass es besser wäre wenn du eine User Tabelle und eine Online-Zeit Tabelle hast.

                    In der Online Zeit tabelle hast du für jeden Tag, den der User online sein will eine Zeile. Dabei wir der User über seine ID (die der User-Tabelle) identifiziert und daneben steht der Jeweilige Tag. Über eine Suche nach der jeweiligen User-ID in der Online-Tabelle bekommst du dann alle Online Tage...

                    Gruß
                    Alex

                    1. Hi!

                      in Verbindung mit den anderen Tipps, die du schon bekommen hast, kommt dann also raus, dass es besser wäre wenn du eine User Tabelle und eine Online-Zeit Tabelle hast.

                      Und dafür braucht er auch noch das Grundlagenwissen: Einführung in Joins.

                      Lo!

                  2. Hi,

                    Jetzt verstehe ich langsam was Ihr meint-kann es aber noch nicht umsetzen.

                    Dann halte dich doch bitte künftig mit dem Meckern etwas zurück, so lange du den Sinn der Antworten noch gar nicht verstanden hast, und frage stattdessen nach, wenn dir etwas unklar ist.

                    MfG ChrisB

                    --
                    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
                  3. Nochmal Hallo,

                    Hallo Supermann,

                    Jetzt verstehe ich langsam was Ihr meint-kann es aber noch nicht umsetzen.

                    Dies ist das SELF, wollen Sie etwas SELF machen wird Ihnen geholfen :)
                    Was du nämlich tun willst ist diese 366 Spalten in Zeilen umwandeln. Damit ist aber nicht gemeint, dass du eine Kalender-Tabelle mit 366 Zeilen und 1000 Spalten (pro User) anlegst, sondern eine mit vier Spalten:
                    Fortlaufende ID
                    User-ID
                    Datum
                    Kommentar (oder wofür auch immer du dein VARCHAR da benötigtest)
                    Je nach Anwendung kann es auch sinnig sein zwei Datum-Spalten zu verwenden (von bis) aber das konnte ich aus deinem Posting nicht herauslesen, also lassen wir das noch :)
                    Wenn ein Benutzer nun einen Tag als "online" schaltet prüfst du nun serverseitig ob das angegebene Datum innerhalb der nächsten zwei Monate liegt.
                    WENN $Eingetragenes_Datum >= heute() UND $Eingetragenes_Datum <= heute()+30 DANN SpeichereInDatenbank($übergebene, $Werte, $aus, $dem, $Formular);
                    Auf der Datenbank machst du dann eine INSERT-Operation, in der du eine Zeile schreibst, darin enthalten die User-ID des Benutzers, das Datum an dem er online ist und sein Kommentar.

                    Beim wieder-offline-schalten musst du dann ggf. die entsprechende Zeile wieder löschen, du identifizierst sie dann über die User-ID und das Datum. Die Fortlaufende ID ist in dieser Tabelle nahezu unnütz, braucht's aber eben :)

                    Bevor du dich mit JOINs beschäftigst (das wäre dann der nächste Schritt) machst du deinen join noch selber außerhalb der Datenbank :)
                    Wenn du jetzt also alle online-Tage von Superheld wissen willst fragst du die Datenbank zuerst
                    SELECT user_id FROM Tabelle_user WHERE uname LIKE 'Superheld'; (ggf. LIMIT, ORDER etc.)
                    zurück kommt die user_id die du dann auf die andere Tabelle los lässt
                    SELECT datum , kommentar FROM Tabelle_onlinezeiten WHERE user_id = ($vorhin_abgefragte_uid) AND datum >= NOW();
                    Wenn du JOINs benutzt ist das nur ein Schritt und du überlässt der Datenbank das zusammenführen von user_id aus der einen und der anderen Tabelle. Dann würdest du nur noch nach dem Benutzernamen fragen und die Datenbank strickt dir das wieder zusammen.

                    Nun zu deinem konkreten Wunsch

                    Dann wollte ich abfragen welcher User überhaupt einen Eintrag hat und dies weiter verarbeiten...

                    Im Grunde machst du das gleiche wie oben, fragst also alle Daten eines Users ab und wenn nichts zurück kommt ist es leer ^^ er hat also nicht "überhaupt einen Eintrag". Um das zu prüfen legst du das LIMIT ggf. noch auf 1 fest, was dann einfach etwas flotter geht.

                    Daher war die Idee das in meine (schlechte) Tabelle die Kürzel des User am entsprechenden Tag eingetragen werden.

                    Lese ich daraus, dass es gar keine User-Tabelle gibt? Falls dem so ist kannst du natürlich auch deine user_id durch die Kürzel ersetzen und nach denen suchen. Ist aber nicht so performant.

                    Wenn du deine Tabellen entsprechend umgestickt hast kannst du dich auch mit JOINs beschäftigen, die das ganze wie erwähnt noch stärker vereinfachen (Dinge die du im Moment dann mit zwei queries verarbeitest gingen dann direkt auf der Datenbank).

                    --
                    sh:( fo:| ch:? rl:( br:& n4:& ie:{ mo:} va:) de:µ_de:] zu:) fl:( ss:| ls:[ js:(
      2. Hallo,

        fast richtig. Es wird aber kein Datum eingetragen sondern nur der Wert 0 oder 1.
        Wie kann ich die id der Zeile abfragen, in der mindestens eines der Felder _01_01 bis _31_12 nicht ller ist bzw. den Wert 1 hat?

        wie frage ich ab, ob mindestens eines der Felder nicht leer ist?

          
        -- Wenn alle Felder leer sind, das heißt den speziellen Wert NULL enthalten,  
        -- dann liefert COALESCE() mit allen Spalten als Argument den Wert NULL zurück.  
        -- ISNULL() liefert somit genau dann True zurück, wenn alle Spalten leer sind.  
        -- NOT ISNULL liefert daher True zurück, wenn in mindestens einer Spalte ein  
        -- von NULL verschiedener Wert steht.  
        SELECT  
            [link:http://dev.mysql.com/doc/refman/5.1/en/logical-operators.html#operator_not@title=NOT] [link:http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html#function_isnull@title=ISNULL](  
                   [link:http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html#function_coalesce@title= COALESCE](  
                    _01_01,  
                    _01_02,  
                    ...  
                    _31_12  
                )  
            ) nicht_alle_leer  
        
        

        Ob eines der Felder den Wert 1 hat kannst Du analog mit GREATEST() in Kombination mit über Deine Spaltenliste mit Anwendung der Funktion COALESCE() auf jede einzelne Spalte ermitteln.

        Ach ja: sinnvoll ist das trotzdem nicht. Sinnvoll ist - wie Dir mehrfach nahegelegt - ein anderes Tabellendesign.

        Sei ein Superheld und springe über Deinen Schatten!

        Freundliche Grüße

        Vinzenz