2010-05-13 17 views
10

Estoy usando T-SQL con ASP.NET, y C# y soy bastante nuevo en SQL.combinando resultados de dos declaraciones de selección

Me preguntaba cómo podría combinar los resultados de dos consultas

Consulta1:

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 

sería muy apreciada Cualquier ayuda . Gracias de antemano

+2

... ¿por qué quieres combinarlos? –

+0

Desea hacer algo con dos consultas, pero es imposible adivinar qué; 'combinar' es muy vago. – Smandoli

+0

Su primera consulta debería dar un error: 'Column 'tableA.Id' no es válida en la lista de selección porque no está contenida ni en una función de agregado ni en la cláusula GROUP BY. –

Respuesta

26

Puede usar un Union.

Esto devolverá los resultados de las consultas en filas separadas.

Primero debe asegurarse de que ambas consultas devuelvan columnas idénticas.

entonces usted puede hacer:

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 

Como se ha mencionado, las dos consultas devuelven muy diferentes datos. Probablemente solo desee hacer esto si ambas consultas devuelven datos que podrían considerarse similares.

SO

Se puede utilizar un Ingreso

Si hay algunos datos que se comparte entre las dos consultas. Esto hará que los resultados de las dos consultas en una sola fila unida por el id, que es probablemente más de lo que quieren hacer aquí ...

que podría hacer:

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

Si bien es posible combinar los resultados, le aconsejo que no lo haga.

Tiene dos tipos de consultas fundamentalmente diferentes que devuelven un número diferente de filas, un número diferente de columnas y diferentes tipos de datos. Lo mejor sería dejarlo tal como está: dos consultas separadas.

+0

es para un procedimiento almacenado que devolverá una sola tabla en JSON (solo desea hacer una llamada ajax). No habrá un número diferente de filas y tableA.ID, y tableA.Name están en ambas consultas. – ErnieStings

+0

@ErnieStings: Es posible hacer una llamada JSON sin tener que poner todos sus datos en un solo conjunto de resultados. Su estrategia actual pasará datos duplicados si un usuario es propietario de múltiples tableA. –

5

Probablemente utiliza Microsoft SQL Server que admite Common Table Expressions (CTE) (ver http://msdn.microsoft.com/en-us/library/ms190766.aspx) que son muy amigables para la optimización de consultas. Así que les sugiero a mi favor de la construcción:

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 

Después de algunas experiencias con CTE se le encontrará muy fácil escribir código usando CTE y usted será feliz con el rendimiento.

+0

Esto probablemente dará el mismo error que la consulta original. –

+0

@Mark Byers: No, ** debe ** funcionar sin un error (¡no tomo en consideración los errores de escritura que pude haber cometido)! No estoy seguro de si se debe usar INNER JOIN o OUTER JOIN o UNION para combinar GetUserInformation con GetNumberOfPlans. CTE funciona como una VISTA o tabla temporal, pero mucho más efectiva. Si guarda los resultados de la primera consulta en una tabla temporal y los resultados de la segunda consulta en la segunda tabla, podrá UNIRSE a las tablas. CTE lo hace, pero SQL usa índices ya existentes en tablas existentes. – Oleg

+0

@Mark Byers: para estar absolutamente seguro uno puede combinar tableA con GetUserInformation y GetNumberOfPlans con respecto a OUTER JOIN en ambas subconsultas. Esto dará el resultado más completo – Oleg

Cuestiones relacionadas