2009-06-16 6 views
13

Tengo una consulta que UNIONs dos datasets algo similares, pero ambos tienen algunas columnas que no están presentes en el otro - es decir, las columnas tienen valores NULL en la UNIÓN resultante. El objetivo de la UNIÓN es obtener los datos en un formato amigable para el lado del software.TSQL ORDER-BY con una UNIÓN de conjuntos de datos dispares

El problema es que necesito ORDENAR los datos resultantes utilizando las columnas que solo existen en uno u otro conjunto.

Por ejemplo: Table1 tiene campos ID, Cat, Precio. Table2 tiene campos ID (igual que en la Tabla 1), Nombre, Abbrv.

Mi consulta se parece a algo como esto:

SELECT t1.ID, t1.Cat, t1.Price, NULL as Name, NULL as Abbrv FROM t1
UNION
SELECT t2.ID, NULL as Cat, NULL as Price, t2.Name, t2.Abbrv FROM t2
ORDER BY Price DESC, Abbrv ASC

El ORDER BY es donde estoy atascado. Los datos se ve así:
100---Balls-----1.53----------------------
200---Bubbles---1.24----------------------
100---------------------RedBall----101RB--
100---------------------BlueBall---102BB--
200---------------------RedWand----201RW--
200---------------------BlueWand---202BW--

Pero yo quiero que se vea como esto:
100---Balls-----1.53----------------------
100---------------------RedBall----101RB--
100---------------------BlueBall---102BB--
200---Bubbles---1.24----------------------
200---------------------RedWand----201RW--
200---------------------BlueWand---202BW--

(disculpas si esas son difíciles de leer - no sabía qué otra manera de mostrar una tabla)

Tenga en cuenta que este es un muy ejemplo embrutecido y el proverbial "use a JOIN!" la respuesta no es aplicable (es decir, ya sé cómo UNIRSE a ellos, pero eso no es lo que quiero en el resultado final).

Bien podría ser que la única forma de lograr esto es manipulando los datos en el software una vez que regrese de la capa de datos, si ese es el caso, entonces que así sea. Pero espero que se pueda hacer en TSQL.

+0

¿La identificación no vincula sus productos T2 con el producto T1? Si no, ¿cómo sabes que RedWand y BlueWand vienen justo después de Bubbles? – mundeep

+0

Él dice en la pregunta: "Tabla2 tiene campos ID (igual que en la Tabla 1)" –

+0

Gracias por todas las respuestas a todos; esta es solo mi primera pregunta, pero esto ya parece una gran comunidad. Además, para aquellos que critiquen la 'arquitectura' que implica mi pregunta, por favor, tenga en cuenta lo que dije arriba y abajo en la respuesta aceptada: ¡esto es un ejemplo simplificado! Las 'tablas' en mi pregunta en realidad representan dos consultas SELECT muy complejas que involucran múltiples tablas y subconsultas, con agregados y campos calculados. ¡Gracias de nuevo! – NateJ

Respuesta

22
Select ID, Cat, Price, Name, Abbrv 
From 
(SELECT t1.ID, t1.Cat, t1.Price, t1.Price AS SortPrice, NULL as Name, NULL as Abbrv 
FROM t1 
UNION 
SELECT t2.ID, NULL as Cat, NULL as Price, t1.Price as SortPrice, t2.Name, t2.Abbrv 
    FROM t2 
    inner join t1 on t2.id = t1.id 
) t3 
ORDER BY SortPrice DESC, Abbrv ASC 

De alguna manera debe saber que los datos en la tabla 2 están vinculados a la tabla 1 y comparten el precio. Dado que Null in abbrv ocupará el primer lugar, no es necesario crear una columna SortAbbrv.

+3

La ejecución de esta consulta produce un error de sintaxis a menos que la subconsulta tenga un alias. Hice la corrección por ti. +1 –

+0

Bien, así que, básicamente, esto es solo poner el precio en la segunda consulta para que pueda ser ordenado. Esta _ sería una gran solución si la consulta real ya no fuera tan complicada: tiene subconsultas y campos agregados y calculados, uno de los cuales es el SORT-er primario (es decir, el precio en este caso). Lo que realmente tendría que hacer es duplicar toda la primera consulta nuevamente para el JOIN en la parte inferior de la UNIÓN. Así que +1 y aceptado, pero no voy a perder más tiempo tratando de que la cosa real funcione así; es mucho más fácil manipular los datos en el código, y probablemente sea más limpio. – NateJ

+0

+1 Buena respuesta Jeff O – Catto

1

Una solución rápida sería hacer 2 inserciones en una tabla temporal o una variable de tabla y como parte de la inserción en la tabla temporal puede establecer una columna de indicador para ayudar con la clasificación y luego ordenar por esa columna de indicador.

+0

Pensé en eso, pero trato de evitarlo. Buena respuesta sin embargo. – NateJ

0

De la parte superior de mi cabeza, diría que el peor de los casos es crear una tabla temporal con todos los campos de hacer una inserción en la tabla temporal de las terminales T1 & T2 después seleccionar la tabla temporal con una orden.

es decir. Crear una tabla temporal (por ejemplo #temp.) Con los campos Id, gato, precio, nombre, abbrv, y luego:

SELECT Id, Cat, Price, null, null INTO #temp FROM T1 
SELECT Id, null, null, Name, Abbrv INTO #temp FROM T2 
SELECT * FROM #temp ORDER BY Id, Price DESC, Abbrv ASC 

NB: No estoy 100% seguro de la sintaxis nula de los insertos, pero yo creo que funcionará

EDITAR: Agregó ordenar por precio & Abbrv después de la identificación ... si Id no vincula T1 & T2 entonces ¿qué hace?

+0

Ignorar la ID; El precio es la ORDER-er principal. – NateJ

2

Debe usar UNION ALL en lugar de UNION para ahorrar el costo de la verificación duplicada.

SELECT * 
FROM 
(
SELECT t1.ID, t1.Cat, t1.Price, NULL as Name, NULL as Abbrv FROM t1 
UNION ALL 
SELECT t2.ID, NULL as Cat, NULL as Price, t2.Name, t2.Abbrv FROM t2 
) as sub 
ORDER BY 
    ID, 
    CASE WHEN Price is not null THEN 1 ELSE 2 END, 
    Price DESC, 
    CASE WHEN Abbrv is not null THEN 1 ELSE 2 END, 
    Abbrv ASC 
+0

La consulta real en la que estoy trabajando tiene UNION TODO. Una vez más, ID no es la ORDEN principal, el precio es. Los ID no se pueden usar para clasificar la consulta 'real' en la que estoy basando esto. – NateJ

Cuestiones relacionadas