2009-02-24 2 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.

Как вы знаете?

Приветствия

+0

Что это за база данных? –

+0

Мне кажется, что ваши таблицы «собаки» и «кошки» просят объединить в таблицу «домашних животных» с колонками (имя, владелец, тип). то вы должны выбрать владельца, тип, счет (имя) из группы домашних животных владельцем, тип. Я думаю. Не тестировал запрос. – rmeador

ответ

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

Извините. Я был уверен, что попробовал. Он отлично работает с именами после круглых скобок. спасибо. –

+0

Этот запрос неверен. Как и предполагается, весь список владельцев находится в обеих таблицах. Даже если вы измените его на LEFT OUTER JOIN, вы предполагаете, что список владельцев полностью находится в основной таблице. Чтобы получить точный список, вам нужно использовать подход UNION ALL. –

+0

Вы правы. Я скопировал его sql и просто добавил псевдоним –

1
  1. Я бы сказал, что вам нужно добавить UNION ALL И.О. просто UNION, чтобы сделать эту работу запроса.
  2. Вам нужно указать свой внутренний выбор.

    SELECT * FROM (SELECT * FROM Table) 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 ...) 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 сразу после подзапрос.

+0

Это было бы правильно, если бы у него было соединение –

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

, это решение не дает правильного ответа. –

+0

Ммм ... да это делает: владелец num_dogs num_cats Боб 2 1 Chuck 1 0 Jon 1 1 Sam 0 1 – 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) 

только потому, что я не люблю союзов и суб выбирает по какой-то причине ... :)

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

SQL план выполнения выходит быстрее, чем принято в настоящее время ответ, тоже :) – Blorgbeard

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; 
Смежные вопросы