JUNTE-SE a dois resultados da instrução SELECT

174

É possível juntar os resultados de 2 SELECTinstruções sql em uma instrução? Eu tenho um banco de dados de tarefas em que cada registro é uma tarefa separada, com prazos (e a PALT, que fica a apenas alguns INTdias do início ao prazo. AgeTambém é um INTnúmero de dias).

Quero ter uma tabela que contenha cada pessoa na tabela, o número de tarefas que eles têm e o número de LATEtarefas que eles têm (se houver).

Eu posso obter esses dados em tabelas separadas facilmente, assim:

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

retornando dados como:

ks        # Tasks
person1   7
person2   3

e então eu tenho:

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

que retorna:

ks        # Late
person1   1
person2   1

E eu quero juntar os resultados dessas duas selectdeclarações (pelo KS)

Estou tentando evitar o uso de uma tabela temporária, mas se essa for a única maneira prática de fazer isso, gostaria de saber mais sobre o uso de tabelas temporárias dessa maneira.

Eu também tentei fazer algum tipo de count() linha que atenda a uma condição, mas também não consegui descobrir como fazer isso. Se for possível, isso também funcionaria.

Adenda: Desculpe, eu quero meus resultados para ter colunas para KS, TaskseLate

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

Além disso, quero que uma pessoa apareça mesmo que não tenha tarefas atrasadas.

SUM(CASE WHEN Age > Palt THEN 1 ELSE 0 END) Late
funciona bem, obrigado por esta resposta!

Duas instruções select também funcionam, usar a LEFT JOINpara se juntar a elas também funciona, e agora eu entendo como unir vários selects dessa maneira

sylverfyre
fonte
Você não deu um exemplo do resultado esperado. Algumas respostas estão, portanto, concatenando resultados. Alguns estão entrando. Qual deles você quer?
Phil
Desculpe, eu quero que meus resultados tenham colunas para KS, Tarefas e KS atrasado # Tarefas # Pessoa atrasada1 7 1 pessoa2 3 1 pessoa3 2 0 (ou nulo) Além disso, quero que uma pessoa apareça mesmo que não tenha tarefas atrasadas . Atualmente, isso é feito usando o método de instrução dois select com LEFT JOIN (em oposição ao INNER JOIN sugerido, que funciona, mas não mostra pessoas sem tarefas tardias, porque elas não existem no segundo SELECT. coluna sendo SUM (CASO QUANDO Idade> Palt THEN 1 ELSE 0 END) Late
sylverfyre

Respostas:

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);
Phil
fonte
1
Isso funciona bem, embora eu não tenha especificado que quero um LEFT JOIN para que os registros apareçam mesmo se eles tiverem 0 tarefas atrasadas.
Sylverfyre
Aceitou esta resposta porque responde a pergunta que fiz melhor, e é formatado para ser uma grande referência em juntar instruções SELECT :)
sylverfyre
Resposta excelente, mas alguém pode dizer que esse tipo de 'solução' é considerado caro ou depende apenas do motivo pelo qual você o está usando?
petrosmm 18/04
71

Tente algo como isto:

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
Mithrandir
fonte
4
Não consegui obter a resposta aceita para o trabalho, mas isso funcionou muito bem para as minhas necessidades. Obrigado.
benvenker
Funcionou como um encanto. Para mim, essa deve ser a resposta aceita. Obrigado.
Nocdib 17/07/19
Trabalhou para mim! Obrigado! Eu também tentei usar várias consultas (várias associações) e também foi ótimo. Se alguém estiver se perguntando, você pode adicionar mais JOINs após o último "ON" no exemplo e continuar usando a sequência: ON .... X JOIN (QUERY N -1) ON Y = ZX JOIN (QUERY N) ON Y = Z
cesarmart 20/12/19
43

Use 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

Ou UNION ALLse você deseja duplicatas:

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
aF.
fonte
3
União ou União Todos terão apenas 2 colunas no resultado. Onde como ele quer que 3 deles
SurajS
14

Se Age e Palt forem colunas na mesma tabela, você poderá contar (*) todas as tarefas e somar apenas as mais atrasadas como esta:

select ks,
       count(*) tasks,
       sum(case when Age > Palt then 1 end) late
  from Table
 group by ks
Nikola Markovinović
fonte
1
Era exatamente isso que eu queria, mas não sabia como procurá-lo. Eu não pensei em usar um SUM (CASE) - obrigado.
Sylverfyre