2009-06-16 16 views
13

Ho una query che UNIONs due set di dati un po 'simili, ma entrambi hanno alcune colonne che non sono presenti nell'altro - cioè le colonne hanno valori NULL nell'UNIONE risultante. Lo scopo di UNION è quello di ottenere i dati in un formato amichevole per il lato software.TSQL ORDER-BY con UNIONE di dataset diversi

Il problema è che ho bisogno di ordinare i dati risultanti utilizzando quelle colonne che esistono solo in uno o l'altro insieme.

Ad esempio: Tabella1 ha campi ID, Cat, Prezzo. Table2 ha ID campi (come in Tabella1), Nome, Abbrv.

La mia domanda assomiglia a qualcosa di simile:

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

L'ORDER BY è dove mi sono bloccato. I dati si presenta così:
100---Balls-----1.53----------------------
200---Bubbles---1.24----------------------
100---------------------RedBall----101RB--
100---------------------BlueBall---102BB--
200---------------------RedWand----201RW--
200---------------------BlueWand---202BW--

Ma io voglio farlo sembrare come questo:
100---Balls-----1.53----------------------
100---------------------RedBall----101RB--
100---------------------BlueBall---102BB--
200---Bubbles---1.24----------------------
200---------------------RedWand----201RW--
200---------------------BlueWand---202BW--

(scusate se quelli sono difficili da leggere - non sapeva quale altro modo per mostrare un tavolo)

Ricorda che questo è un esempio stupefacente stordito e il proverbiale "usa un JOIN!" la risposta non è applicabile (cioè so già come unirmi a loro ma non è quello che voglio nel risultato finale).

Potrebbe essere che l'unico modo per ottenere questo è manipolare i dati nel software una volta che torna dal livello dati - se è così allora così sia. Ma spero che possa essere fatto in TSQL.

+0

L'ID non collega i prodotti T2 al prodotto T1? Se no come fai a sapere che RedWand & BlueWand arrivano subito dopo Bubbles? – mundeep

+0

Nella domanda dice: "La tabella 2 ha i campi ID (come nella tabella 1)" –

+0

Grazie per tutte le risposte a tutti; questa è solo la mia prima domanda, ma questa sembra già una grande comunità. Inoltre, per coloro che criticano l''architettura' che la mia domanda implica, si prega di notare quello che ho detto sopra e sotto nella risposta accettata: questo è un esempio dumbed-down! Le "tabelle" nella mia domanda rappresentano effettivamente due query SELECT molto complesse che coinvolgono più tabelle e sottoquery, con aggregati e campi calcolati. Grazie ancora! – NateJ

risposta

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 

In qualche modo è necessario conoscere i dati nella tabella 2 sono collegati alla tabella 1 e condividere il prezzo. Poiché il valore Null in abbrv verrà prima, non è necessario creare una colonna SortAbbrv.

+3

L'esecuzione di questa query produce un errore di sintassi a meno che la sottoquery non abbia un alias. Ho fatto la correzione per te. +1 –

+0

Giusto, quindi in sostanza questo è solo mettere il prezzo nella seconda query in modo che possa essere ordinato con. Questa dovrebbe essere un'ottima soluzione se la query effettiva non fosse già così complicata: ha subquery e campi aggregati e calcolati, uno dei quali è il SORT-er primario (vale a dire il prezzo in questo caso). Quello che dovrei effettivamente fare è duplicare nuovamente l'intera prima query per il JOIN nella parte inferiore dell'UNION. Quindi +1 e accettato, ma non ho intenzione di perdere altro tempo cercando di far funzionare la cosa vera in questo modo; è molto più facile manipolare i dati nel codice e probabilmente più pulito. – NateJ

+0

+1 Buona risposta Jeff O – Catto

1

Una soluzione rapida sarebbe quella di eseguire 2 inserimenti in una tabella temporanea o una variabile di tabella e come parte di insert nella tabella temporanea è possibile impostare una colonna flag per facilitare l'ordinamento e quindi ordinare per quella colonna flag.

+0

Ci ho pensato, ma ho cercato di evitarlo. Buona risposta però. – NateJ

0

Fuori dalla parte superiore della mia testa direi che nel peggiore dei casi è possibile creare una tabella temporanea con tutti i campi INSERIRE nella tabella temporanea da entrambi T1 & T2 quindi SELEZIONA dalla tabella temporanea con un ordine per.

ie. Creare una tabella temporanea (ad es #temp.) Con campi Id, Gatto, Prezzo, Nome, Abbrv, e poi:

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: Non sono sicuro al 100% sulla sintassi nulla dagli inserti, ma i penso che funzionerà.

MODIFICA: Aggiunto ordine per Prezzo & Abbrv dopo id ... se Id non collega T1 & T2 allora cosa fa?

+0

Ignora l'ID; Il prezzo è l'ORDER-er principale. – NateJ

2

È necessario utilizzare UNION ALL anziché UNION per risparmiare il costo del controllo dei duplicati.

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 query reale su cui sto lavorando è UNION ALL. Ancora una volta, ID non è l'ORDER-er principale, il prezzo è. Gli ID non possono essere utilizzati per l'ordinamento nella query "reale" su cui sto basandomi. – NateJ