Ergebnis 1 bis 9 von 9

Thema: Alternierende Sortierung

  1. #1
    az_hf0 ist offline Neuer Benutzer
    Registriert seit
    15.06.2009
    Beiträge
    23

    Standard Alternierende Sortierung

    Hallo zusammen,

    mir ist heute eine etwas ungewöhnliche Frage eingefallen, die ich gerne mal mit euch diskutieren wollte.

    Angenommen, ich habe eine Tabelle mit Werten wie:

    select * from bereiche order by name;

    name, wert
    Bereich1, 100
    Bereich2, 200
    Bereich3, 20
    Bereich4, 150
    Bereich5, 300

    Der Hintergrund: Wenn man diese in einem Tortendiagramm ausgeben möchte, wäre es besonders übersichtlich, wenn man immer einen größeren Bereich neben einem kleineren Bereich platzieren würde. Zwei kleinere Bereiche nebeneinander sind schlechter lesbar.

    Dabei hätte ich überlegt, wie man denn mit Postgres alternierend sortieren kann. Also so:

    Bereich5, 300
    Bereich3, 20
    Bereich2, 200
    Bereich4, 150
    Bereich1, 100

    Ich habe allerdings keine leichte Lösung gefunden. Klar könnte man mit einer Funktion mitzählen oder modulo2-artig eine Zählspalte mit Sortiergrößen befüllen, aber mich hätte interessiert, ob jemand einen einfacheren Weg kennt, der direkt über das order by führt?

    select * from bereiche order by XYZ?;

    Würde mich freuen, wenn jemand eine intressante oder trickreiche Lösung kennt.

    az_hf0

  2. #2
    symbiont ist offline Erfahrener Benutzer
    Registriert seit
    17.03.2008
    Ort
    NULL
    Beiträge
    1.320

    Standard

    seltsame anforderung ..

    also auch wenn ich von einem tortendiagramm erwarte, dass es die slices der groese nach sortiert rundum aufzeigt .. hier meine antwort zum problem

    du nimmst einfach die datenmenge normal - der groese sortiert

    liest das ergebnis in sowas wie ein array und fuellst das diagramm ueber eine schleife der halben anzahl der elemente (n) an durchlaeufen

    dabei bei jedem durchlauf immer 2 slices gleichzeigt setzen ..
    einen von vorn (index) und einen von n / 2 + index

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

    Standard

    Zitat Zitat von az_hf0 Beitrag anzeigen
    Hallo zusammen,

    mir ist heute eine etwas ungewöhnliche Frage eingefallen, die ich gerne mal mit euch diskutieren wollte.

    Angenommen, ich habe eine Tabelle mit Werten wie:

    select * from bereiche order by name;

    name, wert
    Bereich1, 100
    Bereich2, 200
    Bereich3, 20
    Bereich4, 150
    Bereich5, 300

    Der Hintergrund: Wenn man diese in einem Tortendiagramm ausgeben möchte, wäre es besonders übersichtlich, wenn man immer einen größeren Bereich neben einem kleineren Bereich platzieren würde. Zwei kleinere Bereiche nebeneinander sind schlechter lesbar.

    Dabei hätte ich überlegt, wie man denn mit Postgres alternierend sortieren kann. Also so:

    Bereich5, 300
    Bereich3, 20
    Bereich2, 200
    Bereich4, 150
    Bereich1, 100

    Ich habe allerdings keine leichte Lösung gefunden. Klar könnte man mit einer Funktion mitzählen oder modulo2-artig eine Zählspalte mit Sortiergrößen befüllen, aber mich hätte interessiert, ob jemand einen einfacheren Weg kennt, der direkt über das order by führt?

    select * from bereiche order by XYZ?;

    Würde mich freuen, wenn jemand eine intressante oder trickreiche Lösung kennt.

    az_hf0

    Nettes Problem...

    Ich denke mal, mittels den CTE-Funktionen von 8.4 könnte man da was machen, vielleicht in dieser Art:

    Code:
    test=*# select * from bereiche;
       name   | wert
    ----------+------
     bereich1 |  100
     bereich2 |  200
     bereich3 |   20
     bereich4 |  150
     bereich5 |  300
    (5 Zeilen)
    
    Zeit: 0,204 ms
    test=*# select name, wert from (select *, row_number() over (order by wert desc) from bereiche) foo order by (case when row_number % 2 = 1 then row_number else (select count(1)-row_number from bereiche)  end);
       name   | wert
    ----------+------
     bereich5 |  300
     bereich1 |  100
     bereich2 |  200
     bereich4 |  150
     bereich3 |   20
    (5 Zeilen)
    Die Abfrage:

    Code:
    test=*# select name, wert, row_number from (select *, row_number() over (order by wert desc) from bereiche) foo;
       name   | wert | row_number
    ----------+------+------------
     bereich5 |  300 |          1
     bereich2 |  200 |          2
     bereich4 |  150 |          3
     bereich1 |  100 |          4
     bereich3 |   20 |          5
    (5 Zeilen)
    liefert mir eine Zeilennummer, in der Sortierung ist mein Plan, je nachdem ob diese gerade oder ungerade ist in der sortierten Menge mal von oben und mal von unten zu zählen.

    Ich bin mir aber nicht ganz sicher, ob dies wirklich für alle möglichen Konstellationen funktioniert.

    Vielleicht fällt ja jemand noch was besseres ein...

    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

  4. #4
    symbiont ist offline Erfahrener Benutzer
    Registriert seit
    17.03.2008
    Ort
    NULL
    Beiträge
    1.320

    Standard

    Zitat Zitat von akretschmer Beitrag anzeigen
    Vielleicht fällt ja jemand noch was besseres ein...

    Andreas
    ich lese deine loesungen zu windowing zeuchs zwar wirklich gern aber hier ..

    keep it simple

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

    Standard

    Zitat Zitat von symbiont Beitrag anzeigen
    ich lese deine loesungen zu windowing zeuchs zwar wirklich gern aber hier ..

    keep it simple
    Nun, brauchst ja nicht hinzu schauen. Alternativ, nenne eine bessere Lösung.

    Ich biete mal noch dies:

    Code:
    test=*# select * from (select * from (select *, row_number() over (order by wert) as nr from bereiche) foo where nr%2=1 union all select * from (select *, row_number() over (order by wert desc) as nr from bereiche) foo where nr%2=0) foo order by nr;
       name   | wert | nr
    ----------+------+----
     bereich3 |   20 |  1
     bereich2 |  200 |  2
     bereich4 |  150 |  3
     bereich1 |  100 |  4
     bereich5 |  300 |  5
    (5 Zeilen)

    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
    symbiont ist offline Erfahrener Benutzer
    Registriert seit
    17.03.2008
    Ort
    NULL
    Beiträge
    1.320

    Standard

    Zitat Zitat von akretschmer Beitrag anzeigen
    Nun, brauchst ja nicht hinzu schauen. Alternativ, nenne eine bessere Lösung.
    hab ich doch .. sogar 2
    Code:
       name   | wert | nr
    ----------+------+----
     bereich3 |   20 |  1
     bereich2 |  200 |  2
     bereich4 |  150 |  3
     bereich1 |  100 |  4
     bereich5 |  300 |  5
    (5 Zeilen)

    Andreas
    das ist zwar nett, aber es laesst keine wirkliche "alternierende sortiereung" erkennen ... du muesstestst die ergebnismenge halbieren .. und aufsteigend nach jedem element aus der ersten (kleine) haelfte ein element aus der zweiten (grosse) haelfte einfuegen ..

    daher meinte ich 1. entweder ganz lassen - weils eigentlich quark ist - oder 2. normal sortieren und algorithmisch loesen beim darstellen ..

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

    Standard

    Zitat Zitat von symbiont Beitrag anzeigen
    hab ich doch .. sogar 2


    das ist zwar nett, aber es laesst keine wirkliche "alternierende sortiereung" erkennen ... du muesstestst die ergebnismenge halbieren .. und aufsteigend nach jedem element aus der ersten (kleine) haelfte ein element aus der zweiten (grosse) haelfte einfuegen ..
    Das stimmt natürlich, daher biete ich:

    Code:
    test=*# select * from foo;
     i
    ----
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
    (10 rows)
    
    test=*# with f1 as (select i, row_number() over (order by i)::float   as nr from foo limit (select count(*) from foo)/2), f2 as (select i, row_number() over()::float+0.5 from (select i from foooffset (select count(*) from foo)/2)x) select * from f1  union select * from f2  order by nr;
     i  | nr
    ----+-----
      1 |   1
      6 | 1.5
      2 |   2
      7 | 2.5
      3 |   3
      8 | 3.5
      4 |   4
      9 | 4.5
      5 |   5
     10 | 5.5
    (10 rows)
    daher meinte ich 1. entweder ganz lassen - weils eigentlich quark ist - oder 2. normal sortieren und algorithmisch loesen beim darstellen ..
    Oder 3. die Aufgabe (so sortieren mit SQL) lösen ;-)


    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

  8. #8
    symbiont ist offline Erfahrener Benutzer
    Registriert seit
    17.03.2008
    Ort
    NULL
    Beiträge
    1.320

    Standard

    Zitat Zitat von akretschmer Beitrag anzeigen
    Code:
    test=*# with f1 as (select i, row_number() over (order by i)::float   as nr from foo limit (select count(*) from foo)/2), f2 as (select i, row_number() over()::float+0.5 from (select i from foooffset (select count(*) from foo)/2)x) select * from f1  union select * from f2  order by nr;
     i  | nr
    ----+-----
      1 |   1
      6 | 1.5
      2 |   2
      7 | 2.5
      3 |   3
      8 | 3.5
      4 |   4
      9 | 4.5
      5 |   5
     10 | 5.5
    (10 rows)
    Andreas
    Du Irrer - sieht aber gut aus

    Ich schick dir nächstes Jahr diese Abfrage und frach dich was die macht *lacht*

    Aber is scho' a bissle wie geil

    (auch wenn ich so ein Tortendiagramm nicht wirklich sinnvoll finde)
    Geändert von symbiont (12.10.2009 um 10:50 Uhr)

  9. #9
    az_hf0 ist offline Neuer Benutzer
    Registriert seit
    15.06.2009
    Beiträge
    23

    Standard

    Hallo,

    ganz genau so hatte ich mir das auch vorgestellt. Vom Prinzip her zwei Mengen bilden, diese sortieren und dann alternierend im Resultset zurückgeben. Das WITH-SQL ist natürlich schon ziemlich abgefahren.

    Ich danke euch für die interessanten Vorschläge. Wie gesagt, mir gings hier nur um eine interessante SQL-Idee - klar kann man das Problem auch clientseitig lösen.

    Grüße,
    az_hf0

Ähnliche Themen

  1. Frage ORDER BY Sortierung
    Von cscompute im Forum SQL
    Antworten: 5
    Letzter Beitrag: 28.03.2011, 23:25
  2. Sortierung
    Von minor_73 im Forum SQL
    Antworten: 3
    Letzter Beitrag: 18.12.2009, 11:31
  3. Doppelte Sortierung!?
    Von DaDyne im Forum SQL
    Antworten: 2
    Letzter Beitrag: 16.08.2007, 08:17
  4. Unerwünschte Sortierung
    Von geraldf im Forum Allgemeines
    Antworten: 4
    Letzter Beitrag: 22.01.2007, 14:08
  5. Art der Sortierung
    Von PeeDee im Forum SQL
    Antworten: 12
    Letzter Beitrag: 01.12.2006, 13:31

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