2011-02-02 45 views
5

Esta es mi segunda pregunta de SQL hoy - Soy un poco novato en materia de DBA ...¿Cómo unir los resultados de dos consultas en SQL Server?

Estoy tratando de unir una compleja consulta SQL para fusionar los datos en aproximadamente 12 tablas en 1 sola mesa. Aunque hay una o varias relaciones en la base de datos, sé cuáles serán los números máximos de cada una.

lo tanto, tengo (! Con la ayuda de desbordamiento de pila) aplanar el primer nivel de mi base de datos, y tienen un par de consultas, que ahora debe ser unidas entre sí:

(abreviada)

SELECT 
    A.StudentId, C1.Topic AS SIoC1, C1.Level AS SIoCScore1 
FROM Assessment A 
    LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
WHERE A.Type = 'School' 

SELECT 
    A.StudentId, C1.Topic AS PIoC1, C1.Level AS PIoCScore1 
FROM Assessment A 
    LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
WHERE A.Type = 'Parent' 

¿Es posible nombrar consultas como alias?
O qué más puedo unirme a estas dos consultas por lo que la salida es igual:

| A.Id | SIoC1 | SIoCScore1 | PIoC1 | PIoCScore1 | 

** ACTUALIZACIÓN ** El dominio detrás de esto es que una evaluación se lleva a cabo, en el que tanto la escuela y los padres debe informar. Por lo tanto, la fila única identifica una evaluación que tiene valores tanto de la escuela como de los padres.

Estoy usando SQL Server 2005.

¡Gracias!

* ADEMÁS DE ACTUALIZACIÓN * Esta consulta parece hacer el trabajo ...

SELECT PreConcerns.StudentId, TIoC1, TIoCScore1, PIoC1, PIoCScore1 
FROM 
    Assessment PreConcerns 
    LEFT OUTER JOIN 
    (
    SELECT 
     P.StudentId, C1.Topic AS TIoC1, C1.Level AS TIoCScore1 
    FROM Assessment P 
     LEFT JOIN Concern C1 ON P.Id = C1.Assessment_Id and C1.TopicNumber = 1 
    WHERE P.Type = 'School' 
) scons 
    ON scons.StudentId= PreConcerns.StudentId 
    LEFT OUTER JOIN 
    (
    SELECT 
     P.StudentId, C1.Topic AS PIoC1, C1.Level AS PIoCScore1 
    FROM Assessment P 
     LEFT JOIN Concern C1 ON P.Id = C1.Assessment_Id and C1.TopicNumber = 1 
    WHERE P.Type = 'Parent' 
) pcons 
ON pcons.StudentId = PreConcerns.StudentId 

nueva actualización (toma 2!) ** (no estoy seguro si volviera a abrir esto como una nueva pregunta?!) Volví al trabajo hoy, para encontrar que mi 'solución' anterior no resolvió del todo el problema, crea dos filas para cada evaluación.

Así que para recapitular, que tienen las siguientes tablas:

Student (int:id, varchar(50):name) 
Assessment (int:id, date:date, int:StudentId,) 
Concern (int:id, int:assessment_id, varchar(20):topic, int:level) 

Así que para cada estudiante en el sistema hay exactamente dos evaluaciones - uno con el tipo 'School', y uno con el tipo de 'padre'.

I desea crear una sola fila que combina las evaluaciones y preocupaciones:

(pseudo columnas :)

| Assessment.StudentId | SchoolConcernTopic | SchoolConcernLevel | ParentConcernTopic | ParentConcernLevel | 

o desde el sql anteriormente:

| PreConcerns.StudentId | SIoC1 | SIoCScore1 | PIoC1 | PIoCScore1 | 

Con sólo una fila poblada por alumno, que combina ambas evaluaciones. Tengo la estructura para esto trabajando con el SQL anterior, ¡pero devuelve dos filas! Y no puedo encontrar la forma de actualizar esto para solo devolver uno, ¡cualquier ayuda recibida con gratitud!

Gracias como siempre!

Respuesta

2

Asegúrese de que los nombres de los campos que desea estén especificados en la primera consulta y luego UNION ALL las dos consultas; si quieres un conjunto de resultados etiquetados al final del otro.

Ignora mi primera respuesta, estoy tomando basuras ya que no obtendrá el resultado que deseas. Lo siento.

Si desea que la salida de tener columnas repetidas, donde SIoC1 y PIoC1 son esencialmente lo mismo pero con un nombre diferente dependiendo de si la fila es de una 'escuela' o 'Padre', entonces el conjunto de resultados va a terminar con nulos por todas partes, por ejemplo (Datos aleatorios usados ​​como usted no proporcionan datos de la muestra)

| A.Id | SIoC1 | SIoCScore1 | PIoC1 | PIoCScore1 | 
    1  A   10  NULL  NULL  -- Row type 'School' 
    2  NULL  NULL  B  20   -- Row type 'Parent' 
etc. etc. 

Si los datos se almacenan en la misma tabla, con los mismos nombres de campo utilizan algún otro campo para distinguir las filas, como Type, y la pantalla eso en los resultados.

+0

He actualizado mi pregunta con un poco de dominio fondo - gracias – laura

2

Una consulta puede ser suficiente:

SELECT 
    A.Id, A.Type, C1.Topic AS IoC1, C1.Level AS IoCScore1 
FROM Assessment A 
    LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
WHERE A.Type IN ('School', 'Parent') 
+0

Gracias por la respuesta - lamentablemente esto no conservó las columnas de la escuela y de los padres. – laura

4

Esto se puede hacer con una sola consulta. La cláusula IN es sólo una forma elegante de decir nombres de columna A.Type = 'School' OR A.Type = 'Parent'

SELECT 
    A.Id, C1.Topic AS PIoC1, C1.Level AS PIoCScore1 
FROM Assessment A 
    LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
WHERE A.Type IN ('School','Parent') 
+0

Lamentablemente, esto no mantuvo los puntajes de la escuela y los padres en la misma línea, gracias por la respuesta – laura

+0

@lainie: ¿Qué campos en sus tablas se usan para relacionar los resultados del tipo 'Escuela' con 'Padre'? – Tony

+0

el ID de evaluación vincula los resultados de la escuela y los padres. He actualizado mi pregunta, gracias – laura

0

El resultado debe ser el mismo (el alias utilizado) y los mismos tipos de datos:

SELECT 
    A.Id, C1.Topic AS Topic, C1.Level AS Level 
FROM Assessment A 
    LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
WHERE A.Type = 'School' 

UNION 

SELECT 
    A.Id, C1.Topic AS Topic, C1.Level AS Level 
FROM Assessment A 
    LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
WHERE A.Type = 'Parent' 
+0

Al principio di la misma respuesta, pero luego me di cuenta de que el conjunto de resultados finales que OP quería no es el mismo que el de las columnas de las dos consultas. – Tony

1

podría seleccionar todo en una consulta y usar la instrucción CASE sólo para rellenar los valores en su caso

SELECT 
    A.Id, 
    CASE A.Type 
    WHEN 'School' 
     THEN C1.Topic 
    ELSE NULL 
    END 
    AS SIoC1, 
    CASE A.Type 
    WHEN 'School' 
     THEN C1.Level 
    ELSE NULL 
    END 
    AS SIoCScore1, 
    CASE A.Type 
    WHEN 'Parent' 
     THEN C1.Topic 
    ELSE NULL 
    END 
    AS PIoC1, 
    CASE A.Type 
    WHEN 'Parent' 
     THEN C1.Level 
    ELSE NULL 
    END AS PIoCScore1 
FROM Assessment A 
    LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
WHERE A.Type IN ('School', 'Parent') 

Editar: Preferiblemente, debe almacenar la columna Tipo para que pueda distinguir entre los dos tipos de datos que desea y luego no tendría que repetir las columnas como en el ejemplo anterior. Si está creando una tabla para que se ajuste a alguna forma de normalización, no le conviene tener columnas repetidas; sin embargo, si está utilizando esta declaración de selección en una VISTA, entonces sería aceptable hacerlo.

2

Creo que esta consulta debe devolver el mismo resultado que el de la sección "Actualización adicional".

Las condiciones P.Type = ... se han movido de las secciones DONDE a ENCENDIDO, por lo que puede obtener el efecto deseado sin tener que recurrir a las subselecciones de unión.

SELECT 
    P.StudentId, 
    CS.Topic AS TIoC1, 
    CS.Level AS TIoCScore1, 
    CP.Topic AS PIoC1, 
    CP.Level AS PIoCScore1 
FROM 
    Assessment P 
    LEFT JOIN Concern CS ON P.Id = CS.Assessment_Id 
     and CS.TopicNumber = 1 and P.Type = 'School' 
    LEFT JOIN Concern CP ON P.Id = CP.Assessment_Id 
     and CP.TopicNumber = 1 and P.Type = 'Parent' 

EDIT: Parece que los grupos se deben ayudar allí. (Estoy dejando a mi consulta inicial, de manera que es más fácil ver el cambio necesario para el requisito de actualización.)

SELECT 
    P.StudentId, 
    MAX(CS.Topic) AS TIoC1, 
    MAX(CS.Level) AS TIoCScore1, 
    MAX(CP.Topic) AS PIoC1, 
    MAX(CP.Level) AS PIoCScore1 
FROM 
    Assessment P 
    LEFT JOIN Concern CS ON P.Id = CS.Assessment_Id 
     and CS.TopicNumber = 1 and P.Type = 'School' 
    LEFT JOIN Concern CP ON P.Id = CP.Assessment_Id 
     and CP.TopicNumber = 1 and P.Type = 'Parent' 
GROUP BY P.StudentId 
+0

Gracias por la respuesta, pero esto no hace lo que quiero, ya que crea dos filas por evaluación. – laura

0
SELECT 
    A.Id, 
    CASE A.Type 
    WHEN 'School' 
     THEN C1.Topic 
    ELSE NULL 
    END 
    AS SIoC1, 
    CASE A.Type 
    WHEN 'School' 
     THEN C1.Level 
    ELSE NULL 
    END 
    AS SIoCScore1, 
    CASE A.Type 
    WHEN 'Parent' 
     THEN C1.Topic 
    ELSE NULL 
    END 
    AS PIoC1, 
    CASE A.Type 
    WHEN 'Parent' 
     THEN C1.Level 
    ELSE NULL 
    END AS PIoCScore1 
FROM Assessment A 
    LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
WHERE A.Type IN ('School', 'Parent') 
0

Pruebe esta solución

SELECT * INTO #School FROM 
    (
     SELECT 
     A.StudentId, C1.Topic AS SIoC1, C1.Level AS SIoCScore1 
     FROM Assessment A 
     LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
     WHERE A.Type = 'School' 
     )school 

    SELECT * INTO #Parent FROM 
    (
    SELECT 
     A.StudentId, C1.Topic AS PIoC1, C1.Level AS PIoCScore1 
     FROM Assessment A 
     LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1 
    WHERE A.Type = 'Parent' 
    )parent 

    SELECT 
    SL.StudentId 
    ,SL.SIoC1 
    ,SL.SIoCScore1 
    ,PT.PIoC1 
    ,PT.PIoCScore1 
From #School SL 
LEFT JOIN #Parent PT ON PT.StudentId = SL.StudentId 
Cuestiones relacionadas