Frank: MySQL Sortierung

Hi,

Mattis hat schon mal zu diesem Thema gepostet aber es gab leider keine eindeutige Antwort.

Kann man die Sortierung bei MySQL so beeinflussen, dass man sagt zuerst alles mit Anfangsbuchstabe M, dann S und dann den Rest alphabetisch ausgeben?

Mit ORDER BY name wird ja entweder auf- bzw. absteigen alphabetisch sortiert - ich möchte aber bestimmte Buchstaben zuerst ausgeben.

Oder gibts da ne PHP Lösung?

Vielen Dank, Frank

  1. Hi Frank!

    Um die Daten entsprechend zu sortieren, müsstest Du Dir ein eigenes Sortierfeld zusammenstoppeln (also zB M=1, S=2, Rest=3+Buchstabe) und danach sortieren.

    Ob "select case when ..." in MySQL möglich ist, weiß ich grade nicht - hab ich bis dato nur in Oracle verwendet. Dies wäre eine Möglichkeit, dies im Select umzusetzen - ebenso wie drei Select mit Union.

    Stattdessen würde ich aber einfach drei Abfragen starten - wenn es kein übermäßig großer Datenbestand ist, kein Problem!

    mfg

    norbert =:-)

    1. OK - hab grad nachgesehen - gibt offenbar kein case in MySQL.

      Also dann (feld1 = Namensfeld):

      select '1' as SortField, feld1, feld2
      from table
      where feld1 like 'M%'
      union
      select '2', feld1, feld2
      from table
      where feld1 like 'S%'
      union
      select '3' || feld1, feld1, feld2
      from table
      where feld1 not like 'M%'
      and feld1 not like 'S%'
      order by SortField;

      Nicht getestet - aber so oder ähnlich müsste es hinhauen.

      mfg

      norbert =:-)

      1. Hi

        Nicht getestet - aber so oder ähnlich müsste es hinhauen.

        erstmal DANKE!
        ... bin gerade unterwegs - werde das gleich mal testen.
        Hoffe es klappt - darf ich nochmal nachfragen, wenns Probleme gibt?

        Vielen Dank,
        Frank

        1. Hallo Frank!

          Hoffe es klappt - darf ich nochmal nachfragen, wenns Probleme gibt?

          Ich denke, dazu ist das Forum da ;-)

          mfg

          norbert =:-)

      2. Hi Norbert,

        ich habs so probiert - leider klapps nicht

        $query = "
        select '1' as SortField, lname, fname
        from members
        where lname like 'M%'
        union
        select '2', lname, fname
        from members
        where feld1 like 'S%'
        union
        select '3' || lname, lname, fname
        from members
        where lname not like 'M%'
        and lname not like 'S%'
        order by SortField
        ";
        $result = MYSQL_QUERY($query,$conn);
        while ($row = mysql_fetch_array ($result))
        {
        echo $row["lname"]; //usw.
        }

        members ist meine Tabelle
        lname sind meine Nachnamen, nach denen sortiert werden soll
        fname sind meine Vornamen
        ... dann gibt es noch phone, fax, addr, zip und city

        Was mache ich falsch?
        Danke schon jetzt,
        Frank

        1. Hallo Frank!

          Ich war mir nicht sicher, ob das mit not like ... so hinhaut - aber die Fehlermeldung(en) wären schon recht nützlich ;-)

          Zum Testen kannst Du mal die beiden not like rausnehmen.

          mfg

          norbert =:-)

          1. Hi Norbert

            Zum Testen kannst Du mal die beiden not like rausnehmen.

            hab ich gemacht - allerdings läuft es immer noch nicht :-)
            Fehlermeldung: supplied argument is not a valid MySQL result

            Was nun?

            Kenn mich zwar nicht so gut aus, aber die Sache mit dem
            z.B. select '3' || lname, lname, fname
            Was soll er den selecten, normalerweise gebe ich da, wo jetzt die 1, 2 oder 3 steht immer einen Spaltennamen an ... ???

            Gruss, Frank

            1. Halihallo Frank

              Zum Testen kannst Du mal die beiden not like rausnehmen.

              hab ich gemacht - allerdings läuft es immer noch nicht :-)
              Fehlermeldung: supplied argument is not a valid MySQL result

              Suche nach dieser Fehlermeldung im Archiv. Die Ursache wurde dort oftmals festgehalten!
              Ich Tippe darauf, dass du MySQL der Version 3.xx verwendest: Dort gibt's kein UNION,
              http://www.mysql.de/doc/de/UNION.html.

              Kenn mich zwar nicht so gut aus, aber die Sache mit dem
              z.B. select '3' || lname

              Das scheint mir wirklich mysql-syntaktisch falsch zu sein.

              Was soll er den selecten, normalerweise gebe ich da, wo jetzt die 1, 2 oder 3 steht immer einen Spaltennamen an ... ???

              Nein, Norbert schlägt ein UNION (eine Vereinigungsmenge) vor, für jeden Buchstaben
              eine Ausgabeteilmenge, die dann zusammengeschustert wird, die Sortierung erreicht man
              eben dadurch, dass man jeder Ausgabeteilmenge (sprich, jedem Buchstaben _deines_
              Alphabets) eine Konstante zuweist, nachder man das UNION'ized Erbebnis schön sortieren
              kann (eben sortieren nach deinen Vorstellungen, M=>1, S=>2 => M's kommen zuerst, dann
              alle S's und so weiter).

              Viele Grüsse

              Philipp

              1. Hi Phillipp,

                Ich Tippe darauf, dass du MySQL der Version 3.xx verwendest: Dort gibt's kein UNION,

                Nein, ich benutz MySQL 4.XX

                Nein, Norbert schlägt ein UNION (eine Vereinigungsmenge) vor, für jeden Buchstaben
                eine Ausgabeteilmenge, die dann zusammengeschustert wird, die Sortierung erreicht man
                eben dadurch, dass man jeder Ausgabeteilmenge (sprich, jedem Buchstaben _deines_
                Alphabets) eine Konstante zuweist, nachder man das UNION'ized Erbebnis schön sortieren
                kann (eben sortieren nach deinen Vorstellungen, M=>1, S=>2 => M's kommen zuerst, dann
                alle S's und so weiter).

                Leider verstehe ich davon nicht soviel ...

                Habs jetzt nochmal so probiert, aber es läuft immer noch nicht :-((

                $query = "
                select '1' as SortField, lname, fname
                from members
                where lname like 'M%'
                union
                select '2', lname, fname
                from members
                where lname like 'S%'
                union
                select concat('3', lname), lname, lname, fname
                from members
                order by SortField
                ";

                Aber Eurer Meinung nach sollte das möglich sein???
                Was mache ich falsch?

                Und noch was: Wie binde ich das
                where lname not like 'M%'
                and lname not like 'S%'

                not Like scheint es ja nicht zu geben, oder?

                Vielen, vielen Dank,
                Frank

                1. Hallo Frank!

                  Natürlich sollte das möglich sein - wir fragen ja nicht erst seit gestern Datenbanken ab ;-)

                  Zuerst müssen die Select mit den Unions laufen - dann einfach wieder die not like dazu (funktionieren ziemlich sicher - es lag wohl eher am concat!) - und alles ist ok!

                  Mich würde allerdings noch interessieren, wozu man eine derartige Sortierung überhaupt benötigen könnte!?

                  mfg

                  norbert =:-)

            2. Hallo Frank!

              Nachdem ich meist Oracle verwende, hat sich offenbar ein Fehler eingeschlichen - wie ich nun in der Eile feststellte, gibts in MySQL scheinbar die "||" nicht - also stattdessen:

              select concat('3', lname), lname, fname ...

              Das mit den Zahlen funktioniert allerdings wirklich - Du könntest auch

              select 1 + 1;

              schreiben - Ausgabe einfach 2!

              Muss jetzt weg - hoffe, das passt jetzt - wenn nicht, schau ich morgen nochmal rein!

              mfg

              norbert =:-)

              1. Hi Norbert,

                select concat('3', lname), lname, fname ...

                Habs mal so probiert, leider ohne Erfolg ... :-(((

                $query = "
                select '1' as SortField, lname, fname
                from members
                where lname like 'M%'
                union
                select '2', lname, fname
                from members
                where lname like 'S%'
                union
                select concat('3', lname), lname, lname, fname
                from members
                order by SortField
                ";

                Hoffe, dass ich icht zuviel nerve, aber das wäre echt super, wenn das irgendwie klappen würde ...
                Nachmal tausend Dank,
                Frank

                1. Hallo Frank!

                  Im dritten Select ist ein Feld zuviel - zur Erklärung:

                  Mit Union kannst Du einfach die Ergebnisse mehrerer gleich strukturierter Select verknüpfen - bedeutet: gleich Anzahl von Feldern - gleicher Typ. So gesehen sollte sich die Fehlermeldung geändert haben.

                  $query = "
                  select '1' as SortField, lname, fname
                  from members
                  where lname like 'M%'
                  union
                  select '2', lname, fname
                  from members
                  where lname like 'S%'
                  union
                  select concat('3', lname), lname, fname
                  from members
                  order by SortField
                  ";

                  Wir werden schon noch dahinter kommen ;-)

                  mfg

                  norbert =:-)

                  1. Hallo Norbert,

                    ich sag da nur tausend Dank, die ganze Sache läuft ohne Probleme.
                    Hab ans Ende die NOT LIKES wieder eingefügt und den Rest noch nach lname sortieren lassen - suuuuper.

                    $query = "
                    select '1' as SortField, lname, fname
                    from members
                    where lname like 'M%'
                    union
                    select '2', lname, fname
                    from members
                    where lname like 'S%'
                    union
                    select concat('3', lname), lname, fname
                    from members
                    where lname not like 'M%'
                    and lname not like 'S%'
                    order by SortField,lname
                    ";

                    Ein letzte Frage noch:
                    Wenn ich jetzt mehr als zwei Buchstaben (nicht nur M und S) als "Vorsortierung" angeben will, muss ich dann einfach noch
                    mehrere

                    union
                    select '[X]', lname, fname
                    from members
                    where lname like '[Y]%'

                    und die Anzahl der unions+1 ins Concat setzten? So:

                    union
                    select concat('[Anzahl union+1]', lname), lname, fname

                    Am liebsten würde ich die "Vorsortierung" in einem Array Speichern und das dann Abarbeiten:

                    $array_vorsort=array("M","S","E","G");

                    for($x=0;$x<count($array_vorsort);$x++)
                    {
                    $vorsort1 .= "select '".$x."' as SortField, lname, fname where lname like '".$array_vorsort[$x]."%' union";
                    $vorsort2 .= "lname not like '".$array_vorsort[$x]."%%' and";
                    }

                    ... und dann irgendwie so:

                    $concat=$x+1;

                    $query = "
                    $vorsort1
                    select concat('$concat', lname), lname, fname
                    from members
                    where
                    $vorsort2
                    order by SortField,lname
                    ";

                    ...leider klappt meine Version nicht!

                    Ich sag nochmal vielen, vielen Dank - hätte nie gedacht, dass man das irgendwie lösen kann und ich schon garnicht ...

                    Gruss Frank

                    1. Hallo Frank!

                      1.) Freut mich, dass es klappt - hab ja gesagt, wir schaffen das ;-)

                      2.) Union als solches ist bei Datenbankentwicklern eigentlich verpönt - es gibt auch nur wenige Anwendungsfälle, die ein Union erforderlich machen - aber ich denke, dein Beispiel kommt da ganz gut hin.

                      3.) Natürlich kannst Du das weiter ausbauen - du musst für den "Rest" dann halt auch die "not like" erweitern. Union ist auch nicht besonders ("like" eben so wenig) performant - wenns also mehr Daten sind, kanns sein, das es etwas dauert.

                      4.)Das Beispiel hätt ich fast übersehen...

                      $array_vorsort=array("M","S","E","G");

                      $vorsort = '';

                      /* Alle Selects ... */
                      for($x=0;$x<count($array_vorsort);$x++)
                      {
                         $vorsort .= "select '".$x."' as SortField, lname, fname from members where lname like '".$array_vorsort[$x]."%' union ";
                      }

                      /* ... und jetzt noch den Rest */

                      $vorsort .= "select concat('9', lname), lname, fname from members where ";

                      for($x=0;$x<count($array_vorsort);$x++)
                      {
                         $vorsort .= "lname not like '".$array_vorsort[$x]."%' and ";
                      }

                      /* und damit unser select nicht mit and; endet, einfach noch einen Dummy anhängen */
                      $vorsort .= "1 = 1";

                      So ungefähr - den Rest solltest Du hinbekommen - viel Spaß noch,

                      mfg

                      norbert =:-)

                    2. Bevor dieser Thread im Archiv verschwindet, möchte ich noch anmerken der Vollständigkeit halber noch anmerken, dass diese etwas schwerfällige Lösung nur interessant ist, wenn sich die Anzahl oder Reihenfolge der "neuen" Sortierbegriffe dynamisch ändert.

                      Andernfalls ist zu empfehlen, einfach eine eigene Sortierspalte in der DB anzulegen und direkt beim Einfügen die Sortierkriterien zu generieren - dies ist wesentlich rascher und benötigt viel weniger Resourcen.

                      mfg

                      norbert =:-)

  2. Halihallo Frank

    Mattis hat schon mal zu diesem Thema gepostet aber es gab leider keine eindeutige Antwort.

    [pref:t=44422&m=242158], wenn schon zugeben, dass bereits ein ähnliches Thema behandelt
    wurde, das noch immer im Forum steht, dann wenigstens mit Verlinkung!

    Kann man die Sortierung bei MySQL so beeinflussen, dass man sagt zuerst alles mit Anfangsbuchstabe M, dann S und dann den Rest alphabetisch ausgeben?

    Direkt nein.

    Mit ORDER BY name wird ja entweder auf- bzw. absteigen alphabetisch sortiert - ich möchte aber bestimmte Buchstaben zuerst ausgeben.

    Kurriose Lösung gäbe es schon: Neue Tabelle mit den Buchstaben als Primary Key, eine
    Zahl (order_num) als Attribut, welches die Position des Buchstabens in deinem Alphabet
    sortiert und dann diese Tabelle über einen OUTER JOIN verknüpfen lassen und ORDER BY
    order_num setzen... Aber würde ich nicht empfehlen ;)

    Oder gibts da ne PHP Lösung?

    'türlich.

    Viele Grüsse

    Philipp

  3. Hallo,

    Kann man die Sortierung bei MySQL so beeinflussen, dass man sagt zuerst alles mit Anfangsbuchstabe M, dann S und dann den Rest alphabetisch ausgeben?
    Mit ORDER BY name wird ja entweder auf- bzw. absteigen alphabetisch sortiert - ich möchte aber bestimmte Buchstaben zuerst ausgeben.

    Wenn es bei den drei Fällen (M, S, Sonstiges) bleibt, würde ich es mit if im Order By machen. Mit ACCESS sähe das so aus:

    SELECT Tabelle1.name
    FROM Tabelle1
    ORDER BY IIf(name Like "m*",1 & name, IIf(name Like "s*", 2 & name, 3 & name));

    & = Textverkettung
    IIF(bedingung,dann,sonst)

    sollte es doch auch bei MySQL geben.

    viele Grüße

    Axel