Обход синтаксиса SQL Select - PullRequest
2 голосов
/ 25 февраля 2009

Допустим, у меня есть две существующие таблицы, "собаки" и "кошки":

 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 (select ...)" тип запроса

Вместо этого после "from" должно быть имя таблицы.

К сожалению, я не могу позволить себе иметь временный стол или стол созданный с предложением "в". Мне нужен обходной путь для предлагаемое решение, в котором вложенное предложение select формируется таким образом.

Каково ваше мнение?

Приветствия

Ответы [ 10 ]

4 голосов
/ 25 февраля 2009

Мой 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
3 голосов
/ 25 февраля 2009
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 к счетчику (..) для устранения проблемы.

1 голос
/ 25 февраля 2009

Вот еще один метод, просто для удовольствия.

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
1 голос
/ 25 февраля 2009

Вам необходимо создать псевдоним подзапроса.

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, следующий сразу за подзапросом.

1 голос
/ 25 февраля 2009

", но проблема в том, что sql не поддерживает тип запроса" select * from (select ...) "

Конечно, это так. вам просто нужно дать ему имя типа "выбрать * из (выберите ...) а"

1 голос
/ 25 февраля 2009
  1. Я бы сказал, что вам нужно добавить UNION ALL io просто UNION, чтобы этот запрос работал.
  2. Вам нужно назвать свой внутренний выбор.

    ВЫБРАТЬ * ИЗ (ВЫБРАТЬ * ИЗ таблицы) MyInnerSelect

Лучшим решением было бы создать владельца таблицы и объединить таблицы «собака и кошка».

0 голосов
/ 25 февраля 2009

Можете ли вы создать таблицу владельцев со всеми именами владельцев? Если это так, следующий запрос даст вам результат, который вы ищете:

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;
0 голосов
/ 25 февраля 2009

Еще один вариант - больше для выделения разных способов, чем обязательно для производительности.

В 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)
0 голосов
/ 25 февраля 2009
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 голосов
/ 25 февраля 2009

Вам необходимо создать псевдоним подзапроса:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...