2009-02-24 8 views
2

Disons que j'ai deux tables existantes, « les chiens » et « chats »:SQL Select solution de syntaxe

 
dog_name | owner 
---------+------ 
Sparky | Bob 
Rover | Bob 
Snoopy | Chuck 
Odie  | Jon 

cat_name | owner 
---------+------ 
Garfield | Jon 
Muffy | Sam 
Stupid | Bob 

Comment puis-je écrire une requête avec cette sortie?

 
owner | num_dogs | num_cats 
------+----------+--------- 
Bob |  2 | 1 
Chuck |  1 | 0 
Sam |  0 | 1 
Jon |  1 | 1 

La réponse que j'ai est la prochaine requête

select owner, sum(num_dogs), sum(num_cats) from 
    (select owner, 1 as num_dogs, 0 as num_cats from dogs 
    union 
    select owner, 0 as num_dogs, 1 as num_cats from cats) 
group by owner 

mais le problème est que SQL ne prend pas en charge "select * from (sélectionner ...)" Type de requête

À la place, il doit y avoir un nom de table après "from".

Malheureusement je ne peux me permettre d'avoir une table temporaire ou une table créée avec la clause "select into". J'ai besoin d'une solution de contournement pour la solution proposée où une clause select imbriquée est formée de cette manière.

Quelle est votre opinion?

Vive

+0

Quel type de moteur de base de données est-ce? –

+0

il me semble que vos tables "chiens" et "chats" supplient d'être combinées dans une table "animaux de compagnie" avec les colonnes (nom, propriétaire, type). alors vous devez sélectionner le propriétaire, le type, le nombre (nom) du groupe d'animaux de compagnie par propriétaire, le type. Je pense. N'a pas testé la requête. – rmeador

Répondre

4

Mon SQL fait, juste besoin de nommer la table ... Quelle base de données utilisez-vous?

select owner, sum(num_dogs), sum(num_cats) from 
    (select owner, 1 as num_dogs, 0 as num_cats from dogs 
    union all 
    select owner, 0 as num_dogs, 1 as num_cats from cats) as g 
group by owner 
+0

Désolé. J'étais sûr d'avoir essayé. Fonctionne correctement après la parenthèse. merci. –

+0

Cette requête est incorrecte. Comme il suppose que la liste entière des propriétaires est dans les deux tableaux. Même si vous le changez en LEFT OUTER JOIN, vous supposez que la liste des propriétaires est entièrement dans la table primaire. Pour obtenir la liste exacte, vous devez utiliser l'approche UNION ALL. –

+0

Vous avez raison. J'ai copié son sql et juste ajouté un alias –

1
  1. Je dirais que vous devez ajouter UNION ALL io juste UNION pour faire ce travail de recherche.
  2. Vous devez nommer votre sélection interne.

    SELECT * FROM (SELECT * FROM Table) MyInnerSelect

Une meilleure solution serait de créer un propriétaire de table et rejoindre les chiens & tables de chat.

0

Vous devez créer un alias de la sous-requête:

select sq.owner, sum(sq.num_dogs), sum(sq.num_cats) from 
    (select owner, 1 as num_dogs, 0 as num_cats from dogs 
    union 
    select owner, 0 as num_dogs, 1 as num_cats from cats 
    ) as sq 
group by sq.owner 
1

"mais le problème est que SQL ne prend pas en charge "select * from (sélectionner ...)" type de requête"

Bien sûr que oui. vous avez juste besoin de lui donner un nom comme "select * from (select ...) a"

1

Vous devez aliaser la sous-requête.

select owner, sum(num_dogs), sum(num_cats) 
from (
    select owner, 1 as num_dogs, 0 as num_cats from dogs 
    union all 
    select owner, 0 as num_dogs, 1 as num_cats from cats 
) a 
group by owner 

Notez que le a immédiatement après la sous-requête.

+0

Ce serait correct s'il avait une union tous –

3
create table cats (cat_name varchar(8), owner varchar(8)) 
create table dogs (dog_name varchar(8), owner varchar(8)) 
create table owners (owner varchar(8)) 

insert into owners values ('Jon') 
insert into owners values ('Bob') 
insert into owners values ('Chuck') 
insert into owners values ('Sam') 

insert into dogs values ('Sparky', 'Bob') 
insert into dogs values ('Rover', 'Bob') 
insert into dogs values ('Snoopy', 'Chuck') 
insert into dogs values ('Odie', 'Jon') 

insert into cats values ('Garfield', 'Jon') 
insert into cats values ('Muffy', 'Sam') 
insert into cats values ('Stupid', 'Bob') 

select 
    owners.owner, 
    count(distinct dog_name) as num_dogs, 
    count(distinct cat_name) as num_cats 
from 
    owners 
     left outer join dogs on dogs.owner = owners.owner 
     left outer join cats on cats.owner = owners.owner 
group by owners.owner 

Notez que compte (dog_name) devrait probablement être count (dog_id) ... plusieurs chiens peuvent avoir le même nom différents propriétaires (diable ... même nom même propriétaire est probablement autorisé).

Notez l'ajout de DISTINCT au nombre (..) pour corriger le problème.

+0

cette solution ne donne pas une réponse correcte. –

+0

Uhm ... oui il fait: propriétaire num_dogs num_cats Bob 2 1 1 0 Chuck Jon 1 1 0 1 Sam – user53794

0
select 
coalesce (d.owner, c.owner), 
count(distinct d.dog_name) as num_dogs, 
count(distinct c.cat_name) as num_cats 
from dogs d 
full join cats c on d.owner = c.owner 
group by coalesce (d.owner, c.owner) 

seulement parce que je n'aime pas les syndicats et les sous pour une raison quelconque choisit ... :)

0

une autre prise à ce sujet, plus pour mettre en évidence différentes manières que nécessairement les performances.

Dans SQL Server -

SELECT 
ISNULL(c.owner, d.owner) AS owner, 
COUNT(d.dog_name) num_dogs, 
COUNT(c.cat_name) num_cats 
FROM 
dogs d 
FULL OUTER JOIN 
cats c 
ON 
d.owner = c.owner 
GROUP BY 
c.owner, d.owner 
ORDER BY 
ISNULL(c.owner, d.owner) 
1

Voici une autre méthode, juste pour le plaisir.

select o.owner, nd.numdogs, nc.numcats 
from owners o 
left join (select owner, count(dog_name) as numdogs 
      from dogs 
      group by owner) nd on nd.owner=o.owner 
left join (select owner, count(cat_name) as numcats 
      from cats 
      group by owner) nc on nc.owner=o.owner 
+0

plan d'exécution SQL sort plus vite que la réponse actuellement acceptée, aussi :) – Blorgbeard

0

Pouvez-vous créer une table de propriétaires avec tous les noms de propriétaires? Si oui, la requête suivante vous donnera la sortie que vous recherchez:

SELECT 
    owners.owner, 
    count(distinct dog_name), 
    count(distinct cat_name) 
FROM 
    (
    Owners 
    LEFT JOIN cats ON 
      owners.owner = cats.owner 
    ) 
LEFT JOIN dogs ON 
    Owners.owner = dogs.owner 
GROUP BY 
    Owners.owner;