2

假设我有两个现有的表,“狗”和“猫”:

狗名 | 所有者
 ---------+------
 火花 | 鲍勃
 罗孚 | 鲍勃
 史努比 | 查克
 欧迪 | 乔恩

 猫名 | 所有者
 ---------+------
 加菲猫 | 乔恩
 玛菲 | 山姆
 愚蠢 | 鲍勃

如何使用此输出编写查询?

所有者 | num_dogs | num_cats
 ------+----------+----------
 鲍勃 | 2 | 1
 查克 | 1 | 0
 山姆 | 0 | 1
 乔恩 | 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 (select...)”类型的查询

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

不幸的是,我买不起临时表或使用“select into”子句创建的表。对于以这种方式形成嵌套选择子句的建议解决方案,我需要一些解决方法。

你怎么看?

干杯

4

10 回答 10

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
于 2009-02-24T22:05:01.243 回答
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

请注意,count(dog_name) 可能应该是 count(dog_id)... 多只狗可以有相同的名字不同的所有者(哎呀......可能允许同名相同的所有者)。

请注意将 DISTINCT 添加到 count(..) 以纠正问题。

于 2009-02-24T22:16:20.110 回答
1
  1. 我想说你需要添加 UNION ALL io just UNION 才能使这个查询工作。
  2. 您需要命名您的内部选择。

    SELECT * FROM (SELECT * FROM Table) MyInnerSelect

更好的解决方案是创建一个表 Owner 并加入 dog & cat 表。

于 2009-02-24T22:03:58.953 回答
1

“但问题是sql不支持“select * from (select...)”类型的查询”

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

于 2009-02-24T22:08:09.957 回答
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紧跟在子查询之后的内容。

于 2009-02-24T22:09:07.223 回答
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
于 2009-02-24T22:47:09.113 回答
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
于 2009-02-24T22:07:10.740 回答
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)

只是因为出于某种原因我不喜欢联合和子选择... :)

于 2009-02-24T22:25:02.223 回答
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)
于 2009-02-24T22:25:48.167 回答
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;
于 2009-02-24T22:54:16.833 回答