Announcement

Collapse
No announcement yet.

SQL Gruppen sortieren

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • SQL Gruppen sortieren

    Ich habe hier DB Einträge, ungefähr nach dem folgenden Schema

    ID, FremdID, Datum, Text
    1, 2, 1.4.2013, Test1
    2, 2, 4.4.2013, Test2
    3, 3, 2.4.2013, Test3
    4, 3, 5.4.2013, Test4
    5, 3, 6.4.2013, Test5
    6, 1, 3.4.2013, Test6
    7, 1, 5.4.2013, Test7


    Ich hätte jetzt gerne eine Abfrage, die zuerst nach Datum und dann nach der FremdID sortiert.

    1, 2, 1.4.2013, Test1
    2, 2, 4.4.2013, Test2
    6, 1, 3.4.2013, Test6
    7, 1, 5.4.2013, Test7
    3, 3, 4.4.2013, Test3
    4, 3, 5.4.2013, Test4
    5, 3, 6.4.2013, Test5

    und nicht

    1,2, 1.4.2013, Test1
    6, 1, 3.4.2013, Test6
    2, 2, 4.4.2013, Test2
    3, 3, 4.4.2013, Test3
    4, 3, 5.4.2013, Test4
    7, 1, 5.4.2013, Test7
    5, 3, 6.4.2013, Test5

    Meine Konstrukte mit ORDER BY Datum,FremdID (oder auch umgekehrt) bringen nur nach Datum sortierte Einträge, aber keine 'Gruppierung' nach FremdID und Sortierung nach Datum über die ganze List.

    Lässt sich das überhaupt mit SQL realisieren?

  • #2
    Hallo,
    Originally posted by cnow View Post
    ...Ich hätte jetzt gerne eine Abfrage, die zuerst nach Datum und dann nach der FremdID sortiert.

    1, 2, 1.4.2013, Test1
    2, 2, 4.4.2013, Test2
    6, 1, 3.4.2013, Test6
    7, 1, 5.4.2013, Test7
    3, 3, 4.4.2013, Test3
    4, 3, 5.4.2013, Test4
    5, 3, 6.4.2013, Test5
    Die Sortierung dieser Liste passt nicht zur Vorgabe!

    Originally posted by cnow View Post
    ...Lässt sich das überhaupt mit SQL realisieren?
    Formuliere deine Sortierreihenfolge korrekt, dann lässt sich das auch mit SQL realisieren.

    Gruß Falk
    Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

    Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

    Comment


    • #3
      Ja ok, das ist vielleicht etwas mißverständlich formuliert.
      'nach FremdID gruppiert' wäre vielleicht richtiger.

      Es sollen immer die Einträge mit der gleichen FremdID zusammenstehen und außerdem nach dem kleinsten Datum je FremdID Eintrag sortiert sein und über die ganze Liste nach Datum sortiert sein.
      Das Beispiel, das ich angegeben hab, passt jedenfalls so, wie ich mir das vorstelle.

      Comment


      • #4
        Originally posted by cnow View Post
        Ja ok, das ist vielleicht etwas mißverständlich formuliert.
        'nach FremdID gruppiert' wäre vielleicht richtiger.

        Es sollen immer die Einträge mit der gleichen FremdID zusammenstehen und außerdem nach dem kleinsten Datum je FremdID Eintrag sortiert sein und über die ganze Liste nach Datum sortiert sein.
        Das Beispiel, das ich angegeben hab, passt jedenfalls so, wie ich mir das vorstelle.
        Ich gebe Falk Recht, Dein Beispiel paßt nicht, und biete:

        Code:
        test=*# select * from cnow ;
         id | fremdid |   datum
        ----+---------+------------
          1 |       2 | 2013-04-01
          2 |       2 | 2013-04-04
          3 |       2 | 2013-04-02
          4 |       3 | 2013-04-05
          5 |       3 | 2013-04-06
          6 |       1 | 2013-04-03
          7 |       1 | 2013-04-05
        (7 rows)
        
        Time: 0,160 ms
        test=*# select *, rank() over (partition by fremdid order by datum) from cnow;
         id | fremdid |   datum    | rank
        ----+---------+------------+------
          6 |       1 | 2013-04-03 |    1
          7 |       1 | 2013-04-05 |    2
          1 |       2 | 2013-04-01 |    1
          3 |       2 | 2013-04-02 |    2
          2 |       2 | 2013-04-04 |    3
          4 |       3 | 2013-04-05 |    1
          5 |       3 | 2013-04-06 |    2
        (7 rows)
        Andreas

        Comment


        • #5
          Originally posted by akretschmer View Post
          Ich gebe Falk Recht, Dein Beispiel paßt nicht, und biete:

          Code:
          test=*# select *, rank() over (partition by fremdid order by datum) from cnow;
           id | fremdid |   datum    | rank
          ----+---------+------------+------
            6 |       1 | 2013-04-03 |    1
            7 |       1 | 2013-04-05 |    2
            1 |       2 | 2013-04-01 |    1
            3 |       2 | 2013-04-02 |    2
            2 |       2 | 2013-04-04 |    3
            4 |       3 | 2013-04-05 |    1
            5 |       3 | 2013-04-06 |    2
          (7 rows)
          Andreas
          Ja, fast. Das erste Datum von FremdID2 ist aber kleiner als das von FremdID1.
          Es sollte also folgendes herauskommen:
          Code:
           id | fremdid |   datum    | rank
          ----+---------+------------+------
            1 |       2 | 2013-04-01 |    1
            3 |       2 | 2013-04-02 |    2
            2 |       2 | 2013-04-04 |    3
            6 |       1 | 2013-04-03 |    1
            7 |       1 | 2013-04-05 |    2
            4 |       3 | 2013-04-05 |    1
            5 |       3 | 2013-04-06 |    2
          Ich hab jetzt auch ein bisschen mit partition herumgespielt, komm aber auch auf keinen grünen Zweig.

          Comment


          • #6
            [Highlight=SQL]select o.id, o.fremdid, o.datum, (select min(datum) from cnow i where i.fremdid = o.fremdid) as minFremdIdDate
            from cnow o
            order by 4, o.datum[/Highlight]

            Das könnte aber durcheinander laufen wenn das kleinste Datum in verschiedenen fremdID ~Gruppen~ gleich ist. Da du das Verhalten in dem Fall aber nicht definiert hast überlasse ich das erstmal dem Zufall.

            Etwas besser

            [Highlight=SQL]select o.id, o.fremdid, o.datum
            from (select min(datum) as datum, fremdid from cnow group by fremdid) i
            inner join cnow o on i.fremdid = o.fremdid
            order by i.datum, i.fremdid, o.datum[/Highlight]
            Zuletzt editiert von Ralf Jansen; 11.04.2013, 10:15.

            Comment


            • #7
              Perfekt!
              Danke an alle Beteiligten

              Comment


              • #8
                Lösung mit OVER anstatt GROUP BY
                [HIGHLIGHT="SQL"]WITH Data ( id , fremdid , datum, Test)
                AS ( SELECT 1, 2, CONVERT (DATE, '2013-04-01', 120), 'Test1' UNION ALL
                SELECT 6, 3, CONVERT (DATE, '2013-04-05', 120), 'Test4' UNION ALL
                SELECT 3, 1, CONVERT (DATE, '2013-04-03', 120), 'Test6' UNION ALL
                SELECT 2, 2, CONVERT (DATE, '2013-04-04', 120), 'Test2' UNION ALL
                SELECT 5, 3, CONVERT (DATE, '2013-04-06', 120), 'Test5' UNION ALL
                SELECT 4, 1, CONVERT (DATE, '2013-04-05', 120), 'Test7' UNION ALL
                SELECT 8, 4, CONVERT (DATE, '2013-04-01', 120), 'Test8' UNION ALL
                SELECT 9, 4, CONVERT (DATE, '2013-04-03', 120), 'Test9' UNION ALL
                SELECT 7, 3, CONVERT (DATE, '2013-04-04', 120), 'Test3'
                )
                SELECT *
                INTO #Test
                FROM Data ;
                SELECT * FROM #Test;
                [/HIGHLIGHT]
                unsortiert:
                Code:
                         id     fremdid datum      Test
                ----------- ----------- ---------- -----
                          1           2 2013-04-01 Test1
                          6           3 2013-04-05 Test4
                          3           1 2013-04-03 Test6
                          2           2 2013-04-04 Test2
                          5           3 2013-04-06 Test5
                          4           1 2013-04-05 Test7
                          8           4 2013-04-01 Test8
                          9           4 2013-04-03 Test9
                          7           3 2013-04-04 Test3
                [HIGHLIGHT="SQL"]SELECT T.ID
                , T.FremdID
                , T.Datum
                , T.Test
                , RANK () OVER (ORDER BY MinDate, FremdID) AS Sort
                FROM ( SELECT *
                , MIN (Datum) OVER (PARTITION BY FremdID) AS MinDate
                FROM #Test
                ) AS T
                ORDER BY Sort
                , T.Datum
                ;
                DROP TABLE #Test;
                [/HIGHLIGHT]
                Sortiert;
                Code:
                         ID     FremdID Datum      Test                  Sort
                ----------- ----------- ---------- ----- --------------------
                          1           2 2013-04-01 Test1                    1
                          2           2 2013-04-04 Test2                    1
                          8           4 2013-04-01 Test8                    3
                          9           4 2013-04-03 Test9                    3
                          3           1 2013-04-03 Test6                    5
                          4           1 2013-04-05 Test7                    5
                          7           3 2013-04-04 Test3                    7
                          6           3 2013-04-05 Test4                    7
                          5           3 2013-04-06 Test5                    7

                Comment


                • #9
                  irgendwie hab ich euch hier eine Spielwiese gebaut...
                  danke auch für die andere Lösung

                  Comment

                  Working...
                  X