none
Hilfe bei Abfrage benötigt RRS feed

  • Frage

  • Hallo an alle,

    ich habe ein Problem bei einer Abfrage und ich hoffe ihr könnt mir helfen.

    Folgende Ausgangslage:

    Auftragsnummer          Beschreibung

    1                                 erste Zeile des Auftrags

    1                                zweite Zeile des Auftrags

    1                                 dritte Zeile des Auftrags

    2                                 erste Zeile des Auftrages

    2                                 erste Zeile des Auftrages

    Das heißt ich habe eine vermeintliche eindeutige Aufragsnummer. Da ich nie weiß wie viele Zeile eine Auftragsnummer hat wollte ich den Trick anwenden, das ich in einer Subselect nur die erste Zeile anzeigen lasse. Jedoch weiß ich nicht wie ich die Subselect mit der eigentlichen Abfrage "vereine". Ich müsste ja zuvor noch ein Distinct über die Auftragsnümmer machen.

    SELECT Auftragsnummer = (SELECT Top 1 Auftragsnummer FROM DB  as b where b.Aufragsnummer = a.Auftragsnummer)
    
    FROM DB as a
    
    

    Dadurch vorher kein Distinct über Auftragsnummer "gemacht" wurde ist das Ergebnis dem entsprechend.

    Wie könnte ich das Problem noch lösen? Bin wie immer dankbar über jeden noch so kleinen Hinweis.

    Mittwoch, 15. August 2018 15:12

Antworten

  • Hallo Toot,

    das geht recht einfach, wenn ein Sortierkriterium für Deine Auftragszeilen vorhanden ist. Ich habe mir mal erlaubt, das Beispiel von Christoph etwas anzupassen.

    Declare @MeineDaten as Table(Auftragsnummer int, Pos TINYINT, Beschreibung varchar(100));
    
    Insert into @MeineDaten(Auftragsnummer, Pos, Beschreibung) values
    (1 , 1, 'erste Zeile des Auftrags 1 ')
    ,(1, 2, 'zweite Zeile des Auftrags 1')
    ,(1, 3, 'dritte Zeile des Auftrags 1')
    ,(2, 1, 'erste Zeile des Auftrags 2')
    ,(2, 2, 'erste Zeile des Auftrags 2');
    
    ;WITH R
    AS
    (
    	SELECT	ROW_NUMBER() OVER (PARTITION BY Auftragsnummer ORDER BY Pos) AS RN,
    			Auftragsnummer,
    			Beschreibung
    	FROM	@MeineDaten
    )
    SELECT R.Auftragsnummer, Beschreibung
    FROM R
    WHERE	RN = 1;

    Das Ergebnis ist nun von jeder Auftragsnummer nur noch die erste Zeile.


    Uwe Ricken (Blog | Twitter)
    Microsoft Certiied Master - SQL Server 2008
    Microsoft Certified Solution Master - CHARTER Data Platform
    Microsoft Certified Solution Expert - Data Platform
    db Berater GmbH
    Microsoft SQL Server Blog (german only)

    Donnerstag, 16. August 2018 08:07
  • Hi,

    a) ja, geht problemlos.

    b) poste doch bitte einfach deinen Code, dann kann man dir auch sagen, wo der Fehler liegt.

    WITH Query1 AS
    (
    SELECT   Auftragsnummer,
             Beschreibung,
             ROW_NUMBER() OVER ( PARTITION BY Auftragsnummer 
    WHERE    <Spalte> = '123'
    ORDER BY <Sortierspalte> ) AS RowNumber,
    FROM     <Tabelle>
    ), Query2 AS
    (
    SELECT   Auftragsnummer,
             Beschreibung,
             ROW_NUMBER() OVER ( PARTITION BY Auftragsnummer 
    WHERE    <Spalte> = '456'
    ORDER BY <Sortierspalte> ) AS RowNumber,
    FROM     <Tabelle>
    )
    SELECT Auftragsnummer,
           Beschreibung
    FROM   Query1
    WHERE  RowNumber = 1
    UNION ALL
    SELECT Auftragsnummer,
           Beschreibung
    FROM   Query2
    WHERE  RowNumber = 1
    

    Als einfaches Beispiel.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Donnerstag, 16. August 2018 16:11
    Moderator
  • Hi,

    die Auftragsnummer ist dann ja eindeutig, es ist nur nicht sichergestellt, dass die "erste" Auftragsbeschreibung mitkommt, wenn Du kein eindeutiges Sortierkriterium für diese Sortierung hast.

    Wenn die Tabelle bspw. noch eine fortlaufende, eindeutige ID, eine Positionsnummer innerhalb des Auftrags, ... hat, kann man das wie von Uwe geschrieben machen. Ansonsten kommt halt irgendeine Auftragsbeschreibung zur Auftragsnummer.

    WITH Query AS
    (
    SELECT Auftragsnummer,
           Beschreibung,
           ROW_NUMBER() OVER ( PARTITION BY Auftragsnummer ORDER BY <Sortierspalte> ) AS RowNumber,
    FROM   <Tabelle>
    )
    SELECT Auftragsnummer,
           Beschreibung
    FROM   Query
    WHERE  RowNumber = 1


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Donnerstag, 16. August 2018 09:14
    Moderator

Alle Antworten

  • Hi,

    so ganz verstanden habe ich nicht, was Du da brauchst.

    Ich würde es aber mal so interpretieren, dass Du über alle Datensätze eine eindeutige Auftragsnummer und ggfs. noch die Anzahl der Zeilen haben willst!?

    Falls ja, geht das bspw. so:

    SELECT   Auftragsnummer,
             COUNT( 1 ) AS AnzahlZeilen
    FROM     <Tabelle>
    GROUP BY Auftragsnummer

    Es wäre aber hilfreich, wenn Du uns anhand der Beispieldaten zeigen würdest, welches Ergebnis Du haben willst.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    Mittwoch, 15. August 2018 15:21
    Moderator
  • Willst Du evtl. die "hoffentlich" erste Zeile der Beschreibung zu einem Auftrag haben und mit den anderen Daten joinen?
    Dann könnte man es so machen, wobei die Reihenfolge wirklich zufällig ist und nicht sicher die erste Zeile wiedergibt, wenn Du kein anderes Kriterium für das ORDER BY hast.

    Declare @MeineDaten as Table(Auftragsnummer int, Beschreibung varchar(100));
    
    Insert into @MeineDaten(Auftragsnummer, Beschreibung) values
    (1 , 'erste Zeile des Auftrags 1 ')
    ,(1, 'zweite Zeile des Auftrags 1')
    ,(1, 'dritte Zeile des Auftrags 1')
    ,(2, 'erste Zeile des Auftrags 2')
    ,(2, 'erste Zeile des Auftrags 2');
    
    Select Auftragsnummer, Beschreibung, ROW_NUMBER() OVER(PARTITION BY Auftragsnummer ORDER BY Auftragsnummer) as rn
    from @MeineDaten;
    
    With Vorberechnung as
    (
    Select Auftragsnummer, Beschreibung, ROW_NUMBER() OVER(PARTITION BY Auftragsnummer ORDER BY Auftragsnummer) as rn
    from @MeineDaten)
    Select m.Auftragsnummer, m.Beschreibung, v.Beschreibung as Hoffentlich_Erste_Zeile
    from @MeineDaten m
    Inner Join Vorberechnung v
    	on m.Auftragsnummer = v.Auftragsnummer
    where rn = 1
    ;


    Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu

    Donnerstag, 16. August 2018 06:40
  • Hallo an alle und danke erst mal für eure Ansätze. Ich sehe schon das ich mich wahrscheinlich wieder falsch ausgedrückt habe oder nicht detailreich genug geschrieben habe.

    Ziel ist es:

    Auftragsnummer        Beschreibung

    1                               erste Zeile des Auftrags 1

    2                               erste Zeile des Auftrags 2

    Das heißt ich möchte das die Doppelten oder dreifachen oder noch mehr Auftragsnummer (siehe Beispiel Auftragsnummer 1) nur eine angezeigt wird. Es soll aber die Beschreibung zu der jeweiligen Auftragsnummer stets die erste Zeile genommen werden.  

    Ich hoffe ich konnte es jetzt richtig formulieren ;-)

    Donnerstag, 16. August 2018 07:44
  • Hallo Toot,

    das geht recht einfach, wenn ein Sortierkriterium für Deine Auftragszeilen vorhanden ist. Ich habe mir mal erlaubt, das Beispiel von Christoph etwas anzupassen.

    Declare @MeineDaten as Table(Auftragsnummer int, Pos TINYINT, Beschreibung varchar(100));
    
    Insert into @MeineDaten(Auftragsnummer, Pos, Beschreibung) values
    (1 , 1, 'erste Zeile des Auftrags 1 ')
    ,(1, 2, 'zweite Zeile des Auftrags 1')
    ,(1, 3, 'dritte Zeile des Auftrags 1')
    ,(2, 1, 'erste Zeile des Auftrags 2')
    ,(2, 2, 'erste Zeile des Auftrags 2');
    
    ;WITH R
    AS
    (
    	SELECT	ROW_NUMBER() OVER (PARTITION BY Auftragsnummer ORDER BY Pos) AS RN,
    			Auftragsnummer,
    			Beschreibung
    	FROM	@MeineDaten
    )
    SELECT R.Auftragsnummer, Beschreibung
    FROM R
    WHERE	RN = 1;

    Das Ergebnis ist nun von jeder Auftragsnummer nur noch die erste Zeile.


    Uwe Ricken (Blog | Twitter)
    Microsoft Certiied Master - SQL Server 2008
    Microsoft Certified Solution Master - CHARTER Data Platform
    Microsoft Certified Solution Expert - Data Platform
    db Berater GmbH
    Microsoft SQL Server Blog (german only)

    Donnerstag, 16. August 2018 08:07
  • Genau!

    Ohne Sortierkriterium ist es Zufall, welche Zeile kommt.


    Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu

    Donnerstag, 16. August 2018 08:24
  • Genau das ist ja mein Problem. Es kann sein das ein und die selbe Auftragsnummer mehrfach vorkommt, trotz der Einschränkung mit Kriterien. Deswegen hatte ich die Idee jede Autragsnummer zu prüfen ob diese mehrfach vorkommt. Wenn ja dann nimm nur die Beschreibung der ersten Zeile (also Top 1).

    Aus Performancesicht will ich lieber das ganze gar nicht erst betrachten und aus Sicht der Normalisierung erst recht nicht.

    Habt ihr noch eine Idee wie man das stemmen könnte?  

    Donnerstag, 16. August 2018 09:09
  • Top 1 ohne ORDER BY liefert genauso wenig die erste Zeile wie mein ROW_NUMBER().

    Die von mir gezeigte Lösung liefert Dir eine Zeile pro Auftragsnummer, die Du im Join verwenden kannst. Woran kannst Du denn erkennen, ob es die erste Zeile der Beschreibung ist?


    Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu

    Donnerstag, 16. August 2018 09:13
  • Hi,

    die Auftragsnummer ist dann ja eindeutig, es ist nur nicht sichergestellt, dass die "erste" Auftragsbeschreibung mitkommt, wenn Du kein eindeutiges Sortierkriterium für diese Sortierung hast.

    Wenn die Tabelle bspw. noch eine fortlaufende, eindeutige ID, eine Positionsnummer innerhalb des Auftrags, ... hat, kann man das wie von Uwe geschrieben machen. Ansonsten kommt halt irgendeine Auftragsbeschreibung zur Auftragsnummer.

    WITH Query AS
    (
    SELECT Auftragsnummer,
           Beschreibung,
           ROW_NUMBER() OVER ( PARTITION BY Auftragsnummer ORDER BY <Sortierspalte> ) AS RowNumber,
    FROM   <Tabelle>
    )
    SELECT Auftragsnummer,
           Beschreibung
    FROM   Query
    WHERE  RowNumber = 1


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Donnerstag, 16. August 2018 09:14
    Moderator
  • Soweit so gut. Nur eine Frage habe ich jetzt noch. Ich habe nun zwei WITH´s und ich würde gern das Ergebnis mit einen Union zusammenfügen aber ich bekomme jedes mal die Fehlermeldung das erst die vorherige Anweisung mit einen Semikolon abgeschlossen werden muss.

    Kann man überhaupt 2 With´s mit einander "Verbinden"? 

    Donnerstag, 16. August 2018 15:12
  • Hi,

    a) ja, geht problemlos.

    b) poste doch bitte einfach deinen Code, dann kann man dir auch sagen, wo der Fehler liegt.

    WITH Query1 AS
    (
    SELECT   Auftragsnummer,
             Beschreibung,
             ROW_NUMBER() OVER ( PARTITION BY Auftragsnummer 
    WHERE    <Spalte> = '123'
    ORDER BY <Sortierspalte> ) AS RowNumber,
    FROM     <Tabelle>
    ), Query2 AS
    (
    SELECT   Auftragsnummer,
             Beschreibung,
             ROW_NUMBER() OVER ( PARTITION BY Auftragsnummer 
    WHERE    <Spalte> = '456'
    ORDER BY <Sortierspalte> ) AS RowNumber,
    FROM     <Tabelle>
    )
    SELECT Auftragsnummer,
           Beschreibung
    FROM   Query1
    WHERE  RowNumber = 1
    UNION ALL
    SELECT Auftragsnummer,
           Beschreibung
    FROM   Query2
    WHERE  RowNumber = 1
    

    Als einfaches Beispiel.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Donnerstag, 16. August 2018 16:11
    Moderator