none
Row_Number() in multiple Join RRS feed

  • Frage

  • Hallo allerseits,

    ich habe eine relative Anfängerfrage. Ich bin gerade dabei mich autodidaktisch in das Thema Datenbanken einzuarbeiten.

    Ich suche ständig in irgendwelchen Foren, habe aber für meine spezifische Problemstellung nichts gefunden, was mir weiterhilft.

    Es geht darum eine Row_Number() Column in die Ausgabe eines Querys einzufügen. Prinzipiell habe ich, für einfache Queries, ungefähr verstanden wie es funktioniert, glaube ich.

    Hier mein Query:

    SELECT
    	Topics.TopicText,
    	Questions.QuestionText,
    	Actions.ActionId,
    	Actions.ActionDescription, 
    	Actions.ActionText, 
    	Actions.ActionStart, 
    	Actions.ActionEnd,
    	Questions.TopicId,  
    	Actions.QuestionID,
    	Actions.ActionRotSlider01, 
    	Actions.ActionRotSlider02, 
    	Actions.ActionHorzSlider01, 
    	Actions.ActionIntInput01, 
    	Actions.ActionIntInput02, 
    	Actions.List01, 
    	Actions.List02, 
    	Actions.List03, 
    	Actions.List04, 
    	Actions.Data, 
    	Actions.Kpi, 
    	Actions.Reporting, 
    	Actions.Processes, 
    	Actions.Systems, 
    	Actions.NewOld, 
    	Actions.EyInput      
    
    	FROM Sessions RIGHT JOIN Topics 
    		ON Sessions.SessionId = Topics.SessionId
    		RIGHT JOIN Questions
    		ON Topics.TopicId = Questions.TopicId
    		RIGHT JOIN Actions
    		ON Questions.QuestionId = Actions.QuestionID
    
    	WHERE Sessions.SessionId = 1

    Ich möchte die Ausgabe nach der Höhe der Actions.ActionId aufsteigend sortiert mit einer Row Number versehen.

    da hier die Joins sind, weiss ich nicht wo und wie ich das Subquery für die Zeilennummerierung eintragen soll. 

    Ich bedanke mich im Vorraus.

    lg

    Mittwoch, 25. Juli 2018 13:05

Antworten

  • Hm, erst mal zum SQL selber. Ich zumindest lese auch SQL immer von Links nach Rechts, daher habe ich beim Auftauchen von "Right Joins" so meine Bauchschmerzen, da damit die hierarchische Beziehung der Daten invertiert wird. Ein "Left Join" macht leserlich mehr Sinn.

    Hinzu kommt noch die Bedingung (where) / Beziehung (on). Wenn in der Abfrage auf beiden Seiten Daten vorhanden sind oder sogar vorhanden sein müssen, ist die Abfrage i.d.R. mit "Inner Join" erheblich schneller.

    Deine Abfrage sucht im Moment alle Topics, Actions und Questions und zwar egal, ob eine Session existiert.
    Dieses Ergebnis wird dann allerdings eingeschränkt auf die Sessen 1.
    Hier ist ein Inner Join schneller!

    So nun zu deiner Frage:

    vor From einfach:

    ROW_NUMBER() over (order by Actions.ActionId) as RowId


    • Bearbeitet Der Suchende Donnerstag, 26. Juli 2018 13:29
    • Als Antwort markiert Ventuz Donnerstag, 26. Juli 2018 13:44
    Mittwoch, 25. Juli 2018 13:32

Alle Antworten

  • Hm, erst mal zum SQL selber. Ich zumindest lese auch SQL immer von Links nach Rechts, daher habe ich beim Auftauchen von "Right Joins" so meine Bauchschmerzen, da damit die hierarchische Beziehung der Daten invertiert wird. Ein "Left Join" macht leserlich mehr Sinn.

    Hinzu kommt noch die Bedingung (where) / Beziehung (on). Wenn in der Abfrage auf beiden Seiten Daten vorhanden sind oder sogar vorhanden sein müssen, ist die Abfrage i.d.R. mit "Inner Join" erheblich schneller.

    Deine Abfrage sucht im Moment alle Topics, Actions und Questions und zwar egal, ob eine Session existiert.
    Dieses Ergebnis wird dann allerdings eingeschränkt auf die Sessen 1.
    Hier ist ein Inner Join schneller!

    So nun zu deiner Frage:

    vor From einfach:

    ROW_NUMBER() over (order by Actions.ActionId) as RowId


    • Bearbeitet Der Suchende Donnerstag, 26. Juli 2018 13:29
    • Als Antwort markiert Ventuz Donnerstag, 26. Juli 2018 13:44
    Mittwoch, 25. Juli 2018 13:32
  • Hallo Baldur,

    "Hinzu kommt noch die Bedingung (where) / Beziehung (on). Wenn in der Abfrage auf beiden Seiten Daten vorhanden sind oder sogar vorhanden sein müssen, ist die Abfrage i.d.R. mit "Inner Join" erheblich schneller."

    Das mag in der frühen Steinzeit von RDBMS-Systemen vielleicht so gewesen sein; für moderne Systeme gilt das schon längst nicht mehr. Der Query Optimizer von Microsoft SQL Server ist smart genug, um diesen Widerspruch zu entdecken und einen INNER JOIN zu verwenden.

    -- Abfrage mit LEFT JOIN
    SELECT	C.Name,
    		CO.OrderNumber
    FROM	dbo.Customers AS C
    		LEFT JOIN dbo.CustomerOrders AS CO
    		ON (C.Id = CO.Customer_Id)
    WHERE	CO.OrderDate >= '20140101'
    		AND CO.OrderDate < '20150101';
    GO
    
    -- Abfrage mit INNER JOIN
    SELECT	C.Name,
    		CO.OrderNumber
    FROM	dbo.Customers AS C
    		INNER JOIN dbo.CustomerOrders AS CO
    		ON (C.Id = CO.Customer_Id)
    WHERE	CO.OrderDate >= '20140101'
    		AND CO.OrderDate < '20150101';
    GO

    Beide Abfragen sollen Kunden und Auftragsnummern für 2015 ermitteln. Der Unterschied besteht lediglich in der logischen Verbindung. Für beide Abfragen werden identische Ausführungspläne verwendet, da Microsoft SQL Server erkennt, dass ein OUTER JOIN basierend auf den Prädikaten nicht anwendbar ist (Contradiction).

    Liebe Grüße aus Norwegen...


    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)

    Mittwoch, 25. Juli 2018 14:22
  • Nun, dafür gilt dann die kleine Abkürzung "i.d.R.", was ja weitergehende Optimierungen nicht ausschließt;-).
    Von anderen modernen DBMS'n kenne ich das durchaus ebenso.
    Da ich aber immer wieder erlebe, dass die Whereklausel eben keinen inner join erzwingt, weise ich gerne darauf hin, dass man die Grundregeln des SQL's anwendet bevor man sich auf Optimizer verlässt.

    Es gibt genug Konsortien, die ihre Software mit wenigen 100 Sätzen testen und ausliefern und wenn dann mehrere 100.000 und mehr Sätze auftreten sich dann über mangelnde Performance wundern.
    Zumal die Optimizer, z.T., je nach Datenvolumen auch mal durchaus verschiedene Wege einschlagen.

    Mittwoch, 25. Juli 2018 15:41
  • "...dass man die Grundregeln des SQL's anwendet bevor man sich auf Optimizer verlässt."

    Da bin ich zu 100% bei Dir :)


    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, 26. Juli 2018 13:00
  • Wo kann ich das Bier hinfaxen?
    Donnerstag, 26. Juli 2018 13:09
  • So nun zu deiner Frage:

    vor From einfach:

    ROW_NOMBER() over (order by Actions.ActionId) as RowId

    Also als erstes einmal danke, danke, danke!

    Es tut genau das was ich tun soll. Ich arbeite nicht viel, bzw habe noch gar nicht mit Datenbanken gearbeitet und das was ich jetzt habe, habe ich durch lesen und try and error herausgefunden. Da ich weiss welche Daten ich zu erwarten habe und dass es nicht so viele sein werden, lass ich es auch so. Aber natürlich interessiert mich, was ihr geschrieben habt. Ich habe allerdings das Gefühl, dass ich noch mal grundlegender ansetzen muss. Offensichtlich fehlt mir das Verständnis.

    Habt ihr Vorschläge für Literatur, Online Kurse etc?

    lg

    Donnerstag, 26. Juli 2018 13:26
  • Nun ja, mein erster Vorschlag: Markiere meine Antwort als Lösung für dich:D.

    Ansonsten gibt es viele Vorschläge und Meinungen, fast genau so viele wie Programmierer.
    Eines musst du wissen:
    Auch wenn es nicht so aussieht, SQL hat was mit Programmierung zu tun. Es wird zwar durch die Sprache etwas einfacher, aber das, was man lösen will, muss man sich bereits vorher überlegen.

    Es gibt bestimmt 100te von Büchern, teure und weniger teure Schulungen, Beispiele u.v.m.

    Denke zuest immer an die Aufgabenstellung:
    - was soll ich tun, bzw. was soll das Ergebnis sein
    - wo stehen die Daten
    - liegen sie bereits in der benötigten Form vor
    - welche Abhängigkeit gibt es zwischen den Daten
    - handelt es sich um eine Auswertung (also reines Abfragen)
    - handelt es sich um eine Verarbeitung (also verändern, hinzufügen, löschen, erdichten,...)

    Um seine Daten zu verstehen, benötigt man ein Datenmodell, das die meisten Datenbanken auch unterstützen. Also nicht nur einfach Tabellen, Sichten und Indizes, sondern auch Beziehungen zueinander.

    Wenn du ein solches Schema gehabt hättest, wäre dir der Fehler nicht passiert.

    Einiges kannst du hier durcharbeiten:
    https://docs.microsoft.com/de-de/sql/sql-server/tutorials-for-sql-server-2016?view=sql-server-2017

    und hier bekommst du eine Beispieldatenbank (zugegeben, etwas älter).
    https://docs.microsoft.com/de-de/dotnet/framework/data/adonet/sql/linq/downloading-sample-databases

    Donnerstag, 26. Juli 2018 13:39