2009-02-24 71 views
2

比方说,我有两个现有的表,“狗”和“猫”:SQL SELECT语法的解决方法

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

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

我怎样写这个输出查询?

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

我得到的答复是下一个查询

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 

但问题是,SQL不支持 “SELECT * FROM(选择...)” 型的查询

相反,“from”后面必须有一个表名。

不幸的是,我不能负担得起临时表或使用“select into”子句创建的表 。我需要针对 建议的解决方案采取一些解决方法,其中以这种方式形成嵌套的select子句。

您的意见是?

干杯

+0

这是什么样的数据库引擎? – 2009-02-24 22:29:35

+0

在我看来,你的“狗”和“猫”表正在乞求与列(名称,所有者,类型)组合成一个“宠物”表。那么你会选择所有者,类型,数量(名称)从宠物组所有者,类型。我认为。没有测试查询。 – rmeador 2009-02-24 23:03:04

回答

4

我的SQL确实需要命名该表......您使用的是哪个数据库?

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

对不起。我确信我尝试过。 它可以在括号后命名。 谢谢。 – 2009-02-24 22:12:30

+0

此查询不正确。因为它假定所有者的整个列表都在两个表中。即使您将其更改为LEFT OUTER JOIN,您也假定所有者列表完全位于主表中。要获得准确的列表,您需要使用UNION ALL方法。 – 2009-02-24 22:14:32

+0

你是对的。我复制了他的SQL,并添加了一个别名 – 2009-02-24 22:20:33

1
  1. 我说你需要添加UNION ALL IO只是UNION,使这个查询工作。
  2. 你需要命名你的内部选择。

    SELECT * FROM(SELECT * FROM表)MyInnerSelect

更好的解决方案是创建一个表所有者并加入狗&猫表。

0

您需要别名子查询:

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

“但问题是,SQL不支持 ”SELECT * FROM(选择...)“ 类型的查询”

当然可以。你只需要给它一个名字,如“select * from(select ...)a”

1

你需要别名子查询。

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 

通知的a紧随子查询。

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 

注意,计数(dog_name)大概应该是计数(dog_id)......多狗可以具有相同名称,不同的业主(赫克...相同的名称相同的所有者可能是允许的)。

请注意添加DISTINCT到计数(..)以更正问题。

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) 

只是因为我不喜欢某种原因工会和子选择... :)

0

另取此,更超过一定表现突出不同的方式。

在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

这里的另一种方法,只是为了好玩。

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

您是否可以创建一个拥有所有者名称的所有者表?如果是这样,下面的查询会给你你后面的输出:

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;