JOIN deux résultats de l'instruction SELECT

174

Est-il possible de joindre les résultats de 2 SELECTinstructions SQL en une seule instruction? J'ai une base de données de tâches où chaque enregistrement est une tâche distincte, avec des délais (et un PALT, qui est juste un INTjour du début à la date limite. AgeEst également un INTnombre de jours.)

Je veux avoir un tableau qui a chaque personne dans le tableau, le nombre de tâches qu'ils ont et le nombre de LATEtâches qu'ils ont (le cas échéant).

Je peux facilement obtenir ces données dans des tableaux séparés, comme ceci:

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

renvoyer des données comme:

ks        # Tasks
person1   7
person2   3

et puis j'ai:

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

qui renvoie:

ks        # Late
person1   1
person2   1

Et je veux joindre les résultats de ces deux selectdéclarations (par le KS)

J'essaie d'éviter d'utiliser une table temporaire, mais si c'est le seul moyen pratique de le faire, j'aimerais en savoir plus sur l'utilisation des tables temporaires de cette manière.

J'ai également essayé de créer une sorte de count()lignes qui satisfassent un conditionnel, mais je ne savais pas non plus comment le faire. Si c'est possible, cela fonctionnerait aussi.

Addendum: Désolé, je veux que mes résultats ont des colonnes pour KS, TasksetLate

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

De plus, je veux qu'une personne se présente même si elle n'a pas de tâches en retard.

SUM(CASE WHEN Age > Palt THEN 1 ELSE 0 END) Late
fonctionne bien, merci pour cette réponse!

Deux instructions select fonctionnent également, l'utilisation de a LEFT JOINpour les joindre fonctionne également, et je comprends maintenant comment joindre plusieurs selects de cette manière

Sylverfyre
la source
Vous n'avez pas donné d'exemple du résultat attendu. Certaines réponses sont donc des résultats concaténants. Certains se joignent. Lequel veut-tu?
Phil
Désolé, je veux que mes résultats contiennent des colonnes pour KS, Tâches et KS tardif # Tâches # Personne tardive1 7 1 personne2 3 1 personne3 2 0 (ou null) De plus, je veux qu'une personne se présente même si elle n'a pas de tâches en retard . Actuellement atteint cela en utilisant la méthode à deux instructions SELECT avec un LEFT JOIN (par opposition au INNER JOIN suggéré, qui fonctionne mais ne montre pas les personnes sans tâches en retard car elles n'existent pas dans le deuxième SELECT. colonne étant SUM (CASE WHEN Age> Palt THEN 1 ELSE 0 END) Late
sylverfyre

Réponses:

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
la source
1
Cela fonctionne bien, même si je n'ai pas spécifié que je veux une jointure à gauche pour que les enregistrements apparaissent même s'ils ont 0 tâche en retard.
sylverfyre
J'ai accepté cette réponse car elle répond le mieux à la question que j'ai posée, et elle est formatée pour être une excellente référence sur les instructions JOINing SELECT :)
sylverfyre
Excellente réponse, mais quelqu'un peut-il dire si ce type de «solution» est considéré comme coûteux ou cela dépend simplement de l'utilisation que vous en faites?
petrosmm
71

Essayez quelque chose comme ceci:

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
la source
4
Je n'ai pas pu obtenir la réponse acceptée, mais cela a très bien fonctionné pour mes besoins. Merci.
benvenker
A travaillé comme un charme. En ce qui me concerne, cela devrait être la réponse acceptée. Merci.
nocdib
A travaillé pour moi! Merci! J'ai également essayé d'utiliser plusieurs requêtes (plusieurs jointures) et cela fonctionne également très bien. Si quelqu'un se demande, vous pouvez simplement ajouter plus de JOINs après le dernier "ON" dans l'exemple, et continuer à utiliser la séquence: ON .... X JOIN (QUERY N -1) ON Y = ZX JOIN (QUERY N) ON Y = Z
cesarmart
44

Utilisez 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 ALLsi vous voulez des doublons:

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
un F.
la source
3
Union ou Union All n'aura que 2 colonnes en résultat. Où comme il en veut 3
SurajS
14

Si Age et Palt sont des colonnes dans le même tableau, vous pouvez compter (*) toutes les tâches et ne additionner que les dernières comme ceci:

select ks,
       count(*) tasks,
       sum(case when Age > Palt then 1 end) late
  from Table
 group by ks
Nikola Markovinović
la source
1
C'est exactement ce que je voulais, mais je ne savais pas comment le chercher. Je n'ai pas pensé à utiliser un SUM (CASE) - merci.
sylverfyre