UNISCITI a due risultati dell'istruzione SELECT


174

È possibile unire i risultati di 2 SELECTistruzioni sql in un'unica istruzione? Ho un database di compiti in cui ogni record è un compito separato, con scadenze (e un PALT, che è solo uno INTdei giorni dall'inizio alla scadenza. AgeÈ anche un INTnumero di giorni.)

Voglio avere una tabella che contenga ciascuna persona nella tabella, il numero di attività che hanno e il numero di LATEattività che hanno (se ce ne sono).

Posso ottenere facilmente questi dati in tabelle separate, in questo modo:

SELECT ks, COUNT(*) AS '# Tasks' FROM Table GROUP BY ks

restituzione di dati come:

ks        # Tasks
person1   7
person2   3

e poi ho:

SELECT ks, COUNT(*) AS '# Late' FROM Table WHERE Age > Palt GROUP BY ks

che ritorna:

ks        # Late
person1   1
person2   1

E voglio unire i risultati di queste due selectdichiarazioni (a cura di KS)

Sto cercando di evitare l'uso di una tabella temporanea, ma se questo è l'unico modo pratico per farlo, mi piacerebbe saperne di più sull'uso delle tabelle temporanee in questo modo.

Ho anche provato a fare una sorta di count()file che soddisfa un condizionale, ma non riesco nemmeno a capire come farlo. Se è possibile, funzionerebbe anche quello.

Addendum: Mi dispiace, voglio che i miei risultati hanno colonne per KS, TaskseLate

KS        # Tasks   # Late
person1   7         1
person2   3         1
person3   2         0  (or null)

Inoltre, voglio che una persona si presenti anche se non ha compiti in ritardo.

SUM(CASE WHEN Age > Palt THEN 1 ELSE 0 END) Late
funziona bene, grazie per questa risposta!

LEFT JOINFunzionano anche due affermazioni selezionate, usare anche a per unirle e ora capisco come unire più messaggi selectin questo modo


Non hai fornito un esempio del risultato previsto. Alcune risposte stanno quindi concatenando risultati. Alcuni si stanno unendo. Quale vuoi?
Phil

Spiacenti, voglio che i miei risultati abbiano colonne per KS, Attività e Late KS # Attività # Late person1 7 1 person2 3 1 person3 2 0 (o null) Inoltre, voglio che una persona venga visualizzata anche se non ha attività in ritardo . Attualmente ottenerlo utilizzando il metodo dell'istruzione select due con un JOIN SINISTRO (al contrario del JOIN INNER suggerito, che funziona ma non mostra le persone senza compiti in ritardo perché non esistono nel secondo SELEZIONA Raggiungi anche questo con il ritardo colonna essendo SOMMA (CASO QUANDO Età> Palt THEN 1 ELSE 0 END) Late
sylverfyre

Risposte:


264
SELECT t1.ks, t1.[# Tasks], COALESCE(t2.[# Late], 0) AS [# Late]
FROM 
    (SELECT ks, COUNT(*) AS '# Tasks' FROM Table GROUP BY ks) t1
LEFT JOIN
    (SELECT ks, COUNT(*) AS '# Late' FROM Table WHERE Age > Palt GROUP BY ks) t2
ON (t1.ks = t2.ks);

1
Funziona bene, anche se non ho specificato che voglio un JOIN SINISTRA in modo che i record vengano visualizzati anche se hanno 0 attività in ritardo.
Sylverfyre,

Ha accettato questa risposta perché risponde alla domanda che ho posto meglio, ed è formattato per essere un ottimo riferimento alle istruzioni JOINing SELECT :)
sylverfyre,

Ottima risposta, ma qualcuno può dire che questo tipo di "soluzione" è considerato costoso o dipende solo da cosa lo stai usando?
petrosmm,

71

Prova qualcosa del genere:

SELECT 
* 
FROM
(SELECT ks, COUNT(*) AS '# Tasks' FROM Table GROUP BY ks) t1 
INNER JOIN
(SELECT ks, COUNT(*) AS '# Late' FROM Table WHERE Age > Palt GROUP BY ks) t2
ON t1.ks = t2.ks

4
Non sono riuscito a far funzionare la risposta accettata, ma ha funzionato perfettamente per le mie esigenze. Grazie.
benvenker,

Ha funzionato come un fascino. Per quanto mi riguarda, questa dovrebbe essere la risposta accettata. Grazie.
nocdib,

Ha funzionato per me! Grazie! Ho anche provato a utilizzare più query (più Joins) e anche questo è stato fantastico. Se qualcuno si sta chiedendo, puoi semplicemente aggiungere altri JOIN dopo l'ultimo "ON" nell'esempio e continuare a usare la sequenza: ON .... X JOIN (QUERY N -1) ON Y = ZX JOIN (QUERY N) ON Y = Z
cesarmart il

44

Utilizzare UNION:

SELECT ks, COUNT(*) AS '# Tasks' FROM Table GROUP BY ks
UNION
SELECT ks, COUNT(*) AS '# Late' FROM Table WHERE Age > Palt GROUP BY ks

O UNION ALLse vuoi duplicati:

SELECT ks, COUNT(*) AS '# Tasks' FROM Table GROUP BY ks
UNION ALL
SELECT ks, COUNT(*) AS '# Late' FROM Table WHERE Age > Palt GROUP BY ks

3
Union o Union All avranno solo 2 colonne nel risultato. Dove vuole 3 di loro
SurajS

14

Se Age e Palt sono colonne nella stessa tabella, puoi contare (*) tutte le attività e sommare solo quelle in ritardo come questa:

select ks,
       count(*) tasks,
       sum(case when Age > Palt then 1 end) late
  from Table
 group by ks

1
Questo è ESATTAMENTE quello che volevo, ma non sapevo come cercarlo. Non pensavo di usare un SUM (CASE) - grazie.
Sylverfyre,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.