如何将UNION与COUNT

时间:2015-07-17 15:10:06

标签: sql oracle

我有这个表结构:

TABLE: PERSON     TABLE: CAR

PersonID          PersonID | CarID
------            ---------|---------
1                 1        | 51
                  1        | 52


TABLE: PET          TABLE: AGE

PersonID | PetID    Person | AgeID
---------|----      -------|----
1        | 81       1      | 20
1        | 82
1        | 81

一个人可以拥有许多汽车和宠物,但只有一个年龄。

我想计算某人拥有的汽车数量,计算某人拥有的宠物数量,并列出他们的年龄。

这是我到目前为止所做的:

select
    car.personid as person,
    count(car.carid) as cars,
    null as pets
from car
where car.personid = 1
group by car.personid

union all

select
    pet.personid as person,
    null as cars,
    count(pet.petid) as pets
from pet
where pet.personid = 1
group by pet.personid

这会产生:

Person | Cars | Pets
-------|------|-----
1      | 2    | null
1      | null | 3

但我希望结果看起来像这样:

Person | Cars | Pets | Age
-------|------|------|----
1      | 2    | 3    | 20

这里有一个小提琴:http://sqlfiddle.com/#!3/f584a/1/0

我完全坚持如何将记录放入一行并添加年龄列。

6 个答案:

答案 0 :(得分:3)

SQL Fiddle

查询1

SELECT p.PersonID,
       ( SELECT COUNT(1) FROM CAR c WHERE c.PersonID = p.PersonID ) AS Cars,
       ( SELECT COUNT(1) FROM PET t WHERE t.PersonID = p.PersonID ) AS Pets,
       a.AgeID AS Age
FROM   PERSON p
       LEFT OUTER JOIN
       AGE a
       ON ( p.PersonID = a.PersonID )

<强> Results

| PersonID | Cars | Pets | Age |
|----------|------|------|-----|
|        1 |    2 |    3 |  20 |

查询2

WITH numberOfPets AS (
  SELECT PersonID,
         COUNT(1) AS numberOfPets
  FROM   PET
  GROUP BY PersonID
),
numberOfCars AS (
  SELECT PersonID,
         COUNT(1) AS numberOfCars
  FROM   CAR
  GROUP BY PersonID
)
SELECT p.PersonID,
       COALESCE( numberOfCars, 0 ) AS Cars,
       COALESCE( numberOfPets, 0 ) AS Pets,
       AgeID AS Age
FROM   PERSON p
       LEFT OUTER JOIN AGE a ON ( p.PersonID = a.PersonID )
       LEFT OUTER JOIN numberOfPets t ON ( p.PersonID = t.PersonID )
       LEFT OUTER JOIN numberOfCars c ON ( p.PersonID = c.PersonID )

<强> Results

| PersonID | Cars | Pets | Age |
|----------|------|------|-----|
|        1 |    2 |    3 |  20 |

答案 1 :(得分:2)

应该使用重复的carid或重复的WITH person_cte AS (SELECT * FROM person), car_count AS (SELECT Count(1) AS car, p.personid FROM person_cte p LEFT OUTER JOIN car c ON p.personid = c.personid GROUP BY p.personid), pet_count AS (SELECT Count(1) AS Pet, p.personid FROM person_cte p LEFT OUTER JOIN pet c ON p.personid = c.personid GROUP BY p.personid) SELECT c.personid, c.car, p.pet, a.ageid FROM car_count c INNER JOIN age a ON c.personid = a.personid INNER JOIN pet_count p ON p.personid = c.personid;

SqlFiddle Demo

Carid

如果PetidSELECT p.personid, a.ageid, Count(DISTINCT carid) as carid, Count(DISTINCT petid) as petid FROM person p INNER JOIN age a ON p.personid = a.personid LEFT OUTER JOIN car c ON p.personid = c.personid LEFT OUTER JOIN pet pe ON p.personid = pe.personid GROUP BY p.personid, a.ageid 中没有任何重复项,请使用此

SqlFiddle Demo

server

答案 2 :(得分:1)

我看到的大多数回答中的一个问题是,他们只会包括拥有汽车的人。如果这个人没有车辆但有宠物怎么办?如果他们还没有进入他们的年龄呢?你失去了这个指标。

将人员表作为主要要求。要获得其余的数字,您可以采用各种方法,例如在其他表上使用一系列简单的左外连接并计算其结果。

另请注意标记&#34; ID&#34;在价值的最后是一个用词不当,被认为是糟糕的设计实践。如果它是一个年龄,只需称呼它&#34;年龄&#34;或&#34; age_value&#34;,但不是&#34; AgeID&#34;。我还建议对你的AGE和PERSON表进行非规范化,并使Age(而不是AgeID)成为可以为空的字段。

E.G。

SELECT
  PERSON.PersonID,
  AgeID AS Age,
  CarCount,
  PetCount
FROM
  #PERSON AS PERSON
  LEFT OUTER JOIN AGE AS AGE
    ON AGE.PersonID = PERSON.PersonID
  LEFT OUTER JOIN
    ( SELECT PersonID, COUNT( 1 ) AS CarCount FROM CAR GROUP BY PersonID ) AS CAR
    ON CAR.PersonID = PERSON.PersonID
  LEFT OUTER JOIN
    ( SELECT PersonID, COUNT( 1 ) AS PetCount FROM PET GROUP BY PersonID ) AS PET
    ON PET.PersonID = PERSON.PersonID

答案 3 :(得分:0)

您想要计算不同的汽车/宠物数量吗?如果是这样,请在计数内添加一个独特的。

select
person.personid as person,
count(car.carid) as cars,
count(pet.petid) as pets
age.ageID
from person 
left outer join pet on pet.personid = person.personid
left outer join car on car.personid = person.personid 
left outer join age on age.personid = person.personid
where car.personid = 1
group by car.personid, age.ageID;

答案 4 :(得分:0)

你需要加入单个值,所以在子查询中你的计数

select c.PersonID,a.CarID,b.PetID,c.AgeID from (
            select person.PersonID, COUNT(car.CarID) as CarID
            from Person INNER JOIN Car on Person.PersonID = Car.PersonID
                  group by Person.PersonID) a
            inner join (
            select person.PersonID, COUNT(Pet.PetID) as PetID
            from Person INNER JOIN Pet on Person.PersonID = Pet.PersonID
                  group by Person.PersonID) b
            on a.PersonID = b.PersonID
            inner join (select PersonID,AgeID from Age) c
            on a.PersonID = c.PersonID

答案 5 :(得分:0)

另一种方法是

select person,
sum(cars) as cars,
sum(pets) as pets
from
(
  select
    car.personid as person,
    count(car.carid) as cars,
    null as pets
from car
where car.personid = 1
group by car.personid

union all

select
    pet.personid as person,
    null as cars,
    count(pet.petid) as pets
from pet
where pet.personid = 1
group by pet.personid
) as t
group by person