2010-05-13 6 views
10

Ich benutze T-SQL mit ASP.NET und C# und ich bin ziemlich neu in SQL.kombiniert die Ergebnisse von zwei Select-Anweisungen

Ich habe mich gefragt, wie ich die Ergebnisse von zwei Abfragen kombinieren könnte

Query1:

SELECT tableA.Id, tableA.Name, [tableB].Username AS Owner, [tableB].ImageUrl, [tableB].CompanyImageUrl, COUNT(tableD.UserId) AS NumberOfUsers 
FROM tableD RIGHT OUTER JOIN 
     [tableB] INNER JOIN 
     tableA ON [tableB].Id = tableA.Owner ON tableD.tableAId = tableA.Id 
GROUP BY tableA.Name, [tableB].Username, [tableB].ImageUrl, [tableB].CompanyImageUrl 

Query2:

SELECT tableA.Id, tableA.Name, COUNT([tableC].Id) AS NumberOfPlans 
FROM [tableC] RIGHT OUTER JOIN 
      tableA ON [tableC].tableAId = tableA.Id 
GROUP BY tableA.Id, tableA.Name 

Jede Hilfe wäre sehr willkommen . Vielen Dank im Voraus

+2

... warum möchten Sie sie kombinieren? –

+0

Sie möchten etwas mit zwei Abfragen tun, aber nicht wissen, was; "kombinieren" ist viel zu vage. – Smandoli

+0

Ihre erste Abfrage sollte einen Fehler geben: 'Die Spalte 'tableA.Id' ist in der Auswahlliste ungültig, da sie weder in einer Aggregatfunktion noch in der GROUP BY-Klausel enthalten ist. –

Antwort

26

Sie können eine Union verwenden.

Dadurch werden die Ergebnisse der Abfragen in separaten Zeilen zurückgegeben.

Zuerst müssen Sie sicherstellen, dass beide Abfragen identische Spalten zurückgeben.

Dann können Sie tun:

SELECT tableA.Id, tableA.Name, [tableB].Username AS Owner, [tableB].ImageUrl, [tableB].CompanyImageUrl, COUNT(tableD.UserId) AS Number 
FROM tableD 
RIGHT OUTER JOIN [tableB] 
INNER JOIN tableA ON [tableB].Id = tableA.Owner ON tableD.tableAId = tableA.Id 
GROUP BY tableA.Name, [tableB].Username, [tableB].ImageUrl, [tableB].CompanyImageUrl 

UNION 

SELECT tableA.Id, tableA.Name, '' AS Owner, '' AS ImageUrl, '' AS CompanyImageUrl, COUNT([tableC].Id) AS Number 
FROM 
[tableC] 
RIGHT OUTER JOIN tableA ON [tableC].tableAId = tableA.Id GROUP BY tableA.Id, tableA.Name 

Wie bereits erwähnt wurde, kehren beide Abfragen ganz andere Daten. Wahrscheinlich möchten Sie dies nur tun, wenn beide Abfragen Daten zurückgeben, die als ähnlich angesehen werden können.

SO

Sie können ein

Join verwenden Wenn es einige Daten, die zwischen den beiden Abfragen gemeinsam genutzt wird. Dies wird die Ergebnisse der beiden Abfragen in einer einzigen Zeile durch die ID verbunden setzen, die wahrscheinlich mehr ist, was Sie hier zu wollen tun ...

Sie tun können:

SELECT tableA.Id, tableA.Name, [tableB].Username AS Owner, [tableB].ImageUrl, [tableB].CompanyImageUrl, COUNT(tableD.UserId) AS NumberOfUsers, query2.NumberOfPlans 
FROM tableD 
RIGHT OUTER JOIN [tableB] 
INNER JOIN tableA ON [tableB].Id = tableA.Owner ON tableD.tableAId = tableA.Id 


INNER JOIN 
    (SELECT tableA.Id, COUNT([tableC].Id) AS NumberOfPlans 
    FROM [tableC] 
    RIGHT OUTER JOIN tableA ON [tableC].tableAId = tableA.Id 
    GROUP BY tableA.Id, tableA.Name) AS query2 
ON query2.Id = tableA.Id 

GROUP BY tableA.Name, [tableB].Username, [tableB].ImageUrl, [tableB].CompanyImageUrl 
6

Während es möglich ist, die Ergebnisse zu kombinieren, würde ich davon abraten.

Sie haben zwei grundlegend verschiedene Arten von Abfragen, die eine unterschiedliche Anzahl von Zeilen, eine unterschiedliche Anzahl von Spalten und unterschiedliche Datentypen zurückgeben. Es wäre am besten, es so zu lassen, wie es ist - zwei getrennte Abfragen.

+0

ist für eine gespeicherte Prozedur, die eine einzige Tabelle in JSON zurückgibt (nur einen Ajax-Aufruf). Es wird keine andere Anzahl von Zeilen geben und tableA.ID und tableA.Name sind in beiden Abfragen enthalten. – ErnieStings

+0

@ErnieStings: Es ist möglich, einen JSON-Aufruf zu tätigen, ohne alle Daten in eine einzige Ergebnismenge aufnehmen zu müssen. Ihre aktuelle Strategie wird duplizierte Daten weitergeben, wenn ein Benutzer Eigentümer mehrerer Tabellen ist. –

5

Wahrscheinlich verwenden Sie Microsoft SQL Server, die Common Table Expressions (CTE) unterstützen (siehe http://msdn.microsoft.com/en-us/library/ms190766.aspx), die für die Abfrageoptimierung sehr benutzerfreundlich sind. Deshalb schlage ich Ihnen meine Gunsten Konstruktion:

WITH GetNumberOfPlans(Id,NumberOfPlans) AS (
    SELECT tableA.Id, COUNT(tableC.Id) 
    FROM tableC 
     RIGHT OUTER JOIN tableA ON tableC.tableAId = tableA.Id 
    GROUP BY tableA.Id 
),GetUserInformation(Id,Name,Owner,ImageUrl, 
        CompanyImageUrl,NumberOfUsers) AS (
    SELECT tableA.Id, tableA.Name, tableB.Username AS Owner, tableB.ImageUrl, 
     tableB.CompanyImageUrl,COUNT(tableD.UserId),p.NumberOfPlans 
    FROM tableA 
     INNER JOIN tableB ON tableB.Id = tableA.Owner 
     RIGHT OUTER JOIN tableD ON tableD.tableAId = tableA.Id 
    GROUP BY tableA.Name, tableB.Username, tableB.ImageUrl, tableB.CompanyImageUrl 
) 
SELECT u.Id,u.Name,u.Owner,u.ImageUrl,u.CompanyImageUrl 
    ,u.NumberOfUsers,p.NumberOfPlans 
FROM GetUserInformation AS u 
    INNER JOIN GetNumberOfPlans AS p ON p.Id=u.Id 

Nach einigen Erfahrungen mit CTE werden Sie sehr leicht finden werden, um Code zu schreiben, mit CTE und Sie werden mit der Leistung zufrieden sein.

+0

Dies wird wahrscheinlich den gleichen Fehler wie die ursprüngliche Abfrage geben. –

+0

@Mark Byers: Nein, es ** muss funktionieren ** ohne einen Fehler (ich berücksichtige keine Schreibfehler, die ich machen könnte)! Ich bin nur nicht sicher, ob man INNER JOIN oder einen OUTER JOIN oder UNION verwenden sollte, um GetUserInformation mit GetNumberOfPlans zu kombinieren. CTE funktioniert wie eine Views oder temporäre Tabellen, aber viel effektiver. Wenn Sie die Ergebnisse der ersten Abfrage in einer temporären Tabelle und die Ergebnisse der zweiten Abfrage in der zweiten Tabelle speichern, können Sie die Tabellen verknüpfen. CTE macht dies, aber SQL verwendet bereits vorhandene Indizes für vorhandene Tabellen. – Oleg

+0

@Mark Byers: Um absolut sicher zu sein, kann man TabelleA mit GetUserInformation und GetNumberOfPlans in Bezug auf OUTER JOIN in beiden Unterabfragen kombinieren. Dies ergibt die vollständigste Ergebnismenge – Oleg

Verwandte Themen