Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Aggregierte Abfrage oder Prozedur

Dieses Thema im Forum "Microsoft SQL Server" wurde erstellt von Polyeder, 15 Mai 2020.

  1. Polyeder

    Polyeder Benutzer

    Hallo zusammen,

    ich habe eine Tabelle (tab_xy) mit folgenden Werten:

    Code:
    nr   start                                  end
    1   2020-03-31 08:02:15.000      2020-03-31 08:02:16.000
    1   2020-03-31 08:02:27.000      2020-03-31 08:02:28.000
    1   2020-03-31 08:02:29.000      2020-03-31 08:02:30.000
    1   2020-03-31 08:02:31.000      2020-03-31 08:02:32.000
    2   2020-03-31 08:15:04.000      2020-03-31 08:15:05.000
    2   2020-03-31 08:15:06.000      2020-03-31 08:15:07.000
    2   2020-03-31 08:15:16.000      2020-03-31 08:15:17.000
    3   .                                        .
    3   .                                        .
    3   .                                        .
    .       .                                        .
    .       .                                        .
    .       .                                        .
    
    Hier der dazugehörige Create und Insert-Code (sind nur 2 Nummernläufe):
    Code:
    CREATE TABLE [dbo].[xy](
       [nr] [int],
       [start] [datetime] NOT NULL,
       [end] [datetime] NOT NULL)
    
    insert into [dbo].[xy] ([nr], [start], [end]) values ('1', '2020-03-31T08:02:15.000', '2020-03-31T08:02:16.000');
    insert into [dbo].[xy] ([nr], [start], [end]) values ('1', '2020-03-31T08:02:27.000', '2020-03-31T08:02:28.000');
    insert into [dbo].[xy] ([nr], [start], [end]) values ('1', '2020-03-31T08:02:29.000', '2020-03-31T08:02:30.000');
    insert into [dbo].[xy] ([nr], [start], [end]) values ('1', '2020-03-31T08:02:31.000', '2020-03-31T08:02:32.000');
    insert into [dbo].[xy] ([nr], [start], [end]) values ('2', '2020-03-31T08:15:04.000', '2020-03-31T08:15:05.000');
    insert into [dbo].[xy] ([nr], [start], [end]) values ('2', '2020-03-31T08:15:06.000', '2020-03-31T08:15:07.000');
    insert into [dbo].[xy] ([nr], [start], [end]) values ('2', '2020-03-31T08:15:16.000', '2020-03-31T08:15:17.000');
    
    select * from [dbo].[xy]
    
    Nun will ich das für jede nr nur der kleinste start-Wert und der größte End-Wert in einer Zeile abgebildet wird.

    Das Ergebnis sollte dann folgendermaßen aussehen:
    Code:
    nr     start                                  end
    1      2020-03-31 08:02:15.000     2020-03-31 08:02:32.000
    2      2020-03-31 08:15:04.000     2020-03-31 08:15:17.000
    .       .                                       .
    .       .                                       .
    .       .                                       .
    
    Mein 1. Versuch ist eine Prozedur:
    Code:
    DECLARE    @id_1 integer,
           @id_n integer,
           @start datetime,
           @end datetime
     
    Set @id_1 = (select min(nr) from [tab_xy])
    Set @id_n = (select max(nr) from [tab_xy])
    
    SET @start = (select min([start]) from [tab_xy])
    SET @end = (select max([end]) from [tab_xy])
    
    while @id_1 < @id_n
    
    begin
    
    select @id_1, @start as Beginn, @end as Ende
    set @id_1 = @id_1 + 1
    
    end
    GO
    Ohne die Schleife erhalte ich genau einen Dataset (nämlich den ersten).
    Mit Schleife erhalte ich tausende eigenständige identische Datasets.

    Also ist dieser Weg wohl falsch.

    Wahrscheinlich kann man das mit einer aggregierten Abfrage lösen.
    Jedoch will mir das irgendwie nicht gelingen.

    Beste Grüße
    Polyeder
     
    Zuletzt bearbeitet: 15 Mai 2020
  2. akretschmer

    akretschmer Datenbank-Guru

    select nr, min(start), max(end) from table group by nr;
     
    Polyeder gefällt das.
  3. Polyeder

    Polyeder Benutzer

    Hallo Andreas,

    vielen Dank für die Lösung. War genau das was ich suchte.

    Beste Grüße
    Polyeder

    PS: Woran liegt das eigentlich, dass einem die kompliziertesten Lösungswege immer zuerst einfallen - und die naheliegenden gar nicht?
     
  4. Polyeder

    Polyeder Benutzer

    Hallo,

    ich habe leider noch ein kleines Problem. Ich muss aus dem Feld [start] das Datum im Format TT.MM.JJJJ auslesen.

    Das gelingt mir auch mit:
    Code:
    convert(nvarchar, [start], 104) as Datum
    Jedoch funktioniert danach die gewünschte Darstellung (beim Beispiel oben mit 2 Zeilen) nicht mehr.

    Mein Statement lautet:
    Code:
    SELECT convert(nvarchar, [start], 104) as Datum, nr, min([start]) as Eingang, max([end]) as Abschluss
    FROM dbo.xy
    group by nr, [start]
    Wie muss ich die Abfrage machen, dass ich das folgende als Ergebnisset erhalte:
    Code:
    nr     Datum             Eingang                         Abschluss
    1      31.03.2020       2020-03-31 08:02:15.000     2020-03-31 08:02:32.000
    2      31.03.2020       2020-03-31 08:15:04.000     2020-03-31 08:15:17.000
    
    Beste Grüße
     
    Zuletzt bearbeitet: 19 Mai 2020
  5. akretschmer

    akretschmer Datenbank-Guru

    fassen wir mal kurz zusammen:

    • select nach a,b,max(c) ... group by a,b : funktioniert
    • select nach a, f(b), max(c) ... group by a,b : funktioniert nicht

    findest Du jetzt selber, oder?
     
  6. Polyeder

    Polyeder Benutzer

    Hallo Andreas,

    ich weiß, Du willst mir die Peinlichkeit meiner Dummheit ersparen, dennoch muss ich nachhaken.

    Erstmal hast Du recht, mit folgender Abfrage:
    Code:
    SELECT nr, min([start]) as Eingang, max([end]) as Abschluss, convert(nvarchar, [start], 104) as Datum
    FROM [RS].[dbo].[xy]
    group by nr, convert(nvarchar, [start], 104)
    
    erhalte ich
    Code:
    nr     Datum       Eingang                              Abschluss
    1      31.03.2020       2020-03-31 08:02:15.000     2020-03-31 08:02:32.000
    2      31.03.2020       2020-03-31 08:15:04.000     2020-03-31 08:15:17.000
    Ich hatte das Beispiel leider schlecht gewählt, denn die Tabelle hat noch deutlich mehr Spalten und damit funktioniert die Aggregierung irgendwie nicht mehr.

    Folgendes Beispiel:
    Code:
    CREATE TABLE [dbo].[xy](
       [nr] [int],
       [start] [datetime] NOT NULL,
       [end] [datetime] NOT NULL,
       [Feld01] [int] NOT NULL,
       [Feld02] [int] NOT NULL,
       [Feld03] [varchar](50) NULL)
    
    insert into [dbo].[xy] ([nr], [start], [end], [Feld01], [Feld02], [Feld03])
    values ('1', '2020-03-31T08:02:15.000', '2020-03-31T08:02:16.000', '10', '100', 'text01');
    
    insert into [dbo].[xy] ([nr], [start], [end], [Feld01], [Feld02], [Feld03])
    values ('1', '2020-03-31T08:02:27.000', '2020-03-31T08:02:28.000', '20', '200', 'text02');
    
    insert into [dbo].[xy] ([nr], [start], [end], [Feld01], [Feld02], [Feld03])
    values ('1', '2020-03-31T08:02:29.000', '2020-03-31T08:02:30.000', '30', '300', 'text03');
    
    insert into [dbo].[xy] ([nr], [start], [end], [Feld01], [Feld02], [Feld03])
    values ('1', '2020-03-31T08:02:31.000', '2020-03-31T08:02:32.000', '40', '400', 'text04');
    
    insert into [dbo].[xy] ([nr], [start], [end], [Feld01], [Feld02], [Feld03])
    values ('2', '2020-03-31T08:15:04.000', '2020-03-31T08:15:05.000', '50', '500', 'text05');
    
    insert into [dbo].[xy] ([nr], [start], [end], [Feld01], [Feld02], [Feld03])
    values ('2', '2020-03-31T08:15:06.000', '2020-03-31T08:15:07.000', '60', '600', 'text06');
    
    insert into [dbo].[xy] ([nr], [start], [end], [Feld01], [Feld02], [Feld03])
    values ('2', '2020-03-31T08:15:16.000', '2020-03-31T08:15:17.000', '70', '700', 'text07');
    
    select * from [dbo].[xy]
    Mein select-Statement lautet:
    Code:
    SELECT convert(nvarchar, [start], 104) as Datum, nr, min([start]) as Eingang, max([end]) as Abschluss, [Feld01], [Feld02], [Feld03]
    FROM dbo.xy
    group by [nr], convert(nvarchar, [start], 104), [Feld01], [Feld02], [Feld03]
    mit dem folgenden Ergebnis:

    Code:
    Datum        nr   Eingang                  Abschluss                Feld01  Feld02    Feld03
    31.03.2020   1   2020-03-31 08:02:27.000   2020-03-31 08:02:28.000   20      200      text02
    31.03.2020   1   2020-03-31 08:02:29.000   2020-03-31 08:02:30.000   30      300      text03
    31.03.2020   1   2020-03-31 08:02:31.000   2020-03-31 08:02:32.000   40      400      text04
    31.03.2020   2   2020-03-31 08:15:04.000   2020-03-31 08:15:05.000   50      500      text05
    31.03.2020   2   2020-03-31 08:15:06.000   2020-03-31 08:15:07.000   60      600      text06
    31.03.2020   2   2020-03-31 08:15:16.000   2020-03-31 08:15:17.000   70      700      text07
    
    Witzigerweise ist die 1. Zeile nicht da.
     
  7. akretschmer

    akretschmer Datenbank-Guru

    Dann ist wohl was kaputt ...

    Code:
    test=# create table xy(nr int, start timestamp, ende timestamp, f1 int, f2 int, f3 text);
    CREATE TABLE
    test=*# insert into xy values ('1', '2020-03-31T08:02:15.000', '2020-03-31T08:02:16.000', '10', '100', 'text');
    INSERT 0 1
    test=*# insert into xy values ('1', '2020-03-31T08:02:27.000', '2020-03-31T08:02:28.000', '20', '200', 'text02');
    INSERT 0 1
    test=*# insert into xy values ('1', '2020-03-31T08:02:29.000', '2020-03-31T08:02:30.000', '30', '300', 'text03');
    INSERT 0 1
    test=*# insert into xy values ('1', '2020-03-31T08:02:31.000', '2020-03-31T08:02:32.000', '40', '400', 'text04');
    INSERT 0 1
    test=*# insert into xy values ('2', '2020-03-31T08:15:04.000', '2020-03-31T08:15:05.000', '50', '500', 'text05');
    INSERT 0 1
    test=*# insert into xy values ('2', '2020-03-31T08:15:06.000', '2020-03-31T08:15:07.000', '60', '600', 'text06');
    INSERT 0 1
    test=*# insert into xy values ('2', '2020-03-31T08:15:16.000', '2020-03-31T08:15:17.000', '70', '700', 'text07');
    INSERT 0 1
    test=*# commit;
    COMMIT
    test=# select * from xy;
     nr |        start        |        ende         | f1 | f2  |   f3   
    ----+---------------------+---------------------+----+-----+--------
      1 | 2020-03-31 08:02:15 | 2020-03-31 08:02:16 | 10 | 100 | text
      1 | 2020-03-31 08:02:27 | 2020-03-31 08:02:28 | 20 | 200 | text02
      1 | 2020-03-31 08:02:29 | 2020-03-31 08:02:30 | 30 | 300 | text03
      1 | 2020-03-31 08:02:31 | 2020-03-31 08:02:32 | 40 | 400 | text04
      2 | 2020-03-31 08:15:04 | 2020-03-31 08:15:05 | 50 | 500 | text05
      2 | 2020-03-31 08:15:06 | 2020-03-31 08:15:07 | 60 | 600 | text06
      2 | 2020-03-31 08:15:16 | 2020-03-31 08:15:17 | 70 | 700 | text07
    (7 rows)
    test=*# select start::date, nr, min(start) as eingang, max(ende) as abschluss, f1, f2, f3 from xy group by nr, start::date, f1, f2, f3;
       start    | nr |       eingang       |      abschluss      | f1 | f2  |   f3   
    ------------+----+---------------------+---------------------+----+-----+--------
     2020-03-31 |  2 | 2020-03-31 08:15:16 | 2020-03-31 08:15:17 | 70 | 700 | text07
     2020-03-31 |  1 | 2020-03-31 08:02:15 | 2020-03-31 08:02:16 | 10 | 100 | text
     2020-03-31 |  1 | 2020-03-31 08:02:31 | 2020-03-31 08:02:32 | 40 | 400 | text04
     2020-03-31 |  1 | 2020-03-31 08:02:29 | 2020-03-31 08:02:30 | 30 | 300 | text03
     2020-03-31 |  1 | 2020-03-31 08:02:27 | 2020-03-31 08:02:28 | 20 | 200 | text02
     2020-03-31 |  2 | 2020-03-31 08:15:04 | 2020-03-31 08:15:05 | 50 | 500 | text05
     2020-03-31 |  2 | 2020-03-31 08:15:06 | 2020-03-31 08:15:07 | 60 | 600 | text06
    (7 rows)
    
    test=*#
    
     
  8. Polyeder

    Polyeder Benutzer

    Hmm? Verstehe ich jetzt nicht.
    Was meinst Du damit, dass da was kaputt ist?

    Vielleicht sollte ich noch erwähnen, dass ich auf einem MS SQL-Server 2008 R2 unterwegs bin.
    Aber auch auf dem MS SQL-Server 2017 bekomme ich dasselbe Resultat.

    Die group by-Klausel funktioniert. Aber eben nicht, wenn mehere Spalten in der Tabelle sind.
     
  9. akretschmer

    akretschmer Datenbank-Guru

    Keine Ahnung. Bei mir funktioniert es ja. Ich hab aber auch eine andere DB.
     
  10. Polyeder

    Polyeder Benutzer

    Aber wenn ich das Resultat Deiner Abfrage sehe, dann ist das genau das, was ich auch habe, abgesehen von der 1. Zeile.

    Ah, ich merke gerade, dass ich einen logischen Fehler begehe. Ich habe eine Aggregierung für alle Spalten erwartet. Im Ergebnis dann auch wieder 2 Zeilen. Aber das geht ja gar nicht, da in den anderen Feldern ( [Feld01], [Feld02], [Feld03]) Werte sind und mit dem select-Statement ja nicht klar ist, welche Felder ignoriert werden sollen.

    Wenn ich zusätzliche Daten aus der Tabelle xy benötige, und ich will pro nr nur einen Datensatz, dann muss ich wahrscheinlich mit Underselect oder Union select arbeiten.
     
    Zuletzt bearbeitet: 19 Mai 2020
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden