SQL - группировка по отдельным значениям - PullRequest
1 голос
/ 25 января 2012

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

Я использую ORACLE 10g

Допустим, у меня есть таблица «Производитель» и «Автомобиль», и я хочу подсчитать все вхождения столбца «Car.Name». Вот как бы я это сделал:

SELECT manuf.Name, COUNT(car1.Name), COUNT(car2.Name), COUNT(car3.Name)
FROM Manufacturer manuf 
LEFT JOIN (SELECT * FROM Car c where c.Name = 'Ferrari1') car1 ON manuf.PK = car1.ManufPK
LEFT JOIN (SELECT * FROM Car c where c.Name = 'Ferrari2') car2 ON manuf.PK = car2.ManufPK
LEFT JOIN (SELECT * FROM Car c where c.Name = 'Ferrari3') car3 ON manuf.PK = car3.ManufPK
GROUP BY manuf.Name

Требуются результаты:

Manufacturer | Ferrari1 | Ferrari2 | Ferrari3
----------------------------------------------
Fiat         |    1     |   0      |  5
Ford         |    2     |   3      |  0

Я пробовал это с несколькими левыми соединениями, и это работало нормально. Но когда я добавил много (например, 90+), это было очень медленно (более 1 минуты).

Мой вопрос, есть ли более быстрый способ сделать этот запрос?

Ответы [ 3 ]

3 голосов
/ 25 января 2012

Если вы счастливы видеть машины, отсчитываемые по странице, попробуйте:

select m.Name manufacturer_name,
       c.Name car_name,
       count(*)
from Manufacturer m
left join Car c 
       on m.PK = c.ManufPK and c.Name in ('Ferrari1','Ferrari2','Ferrari3')
group by m.Name, c.Name

Если вам нужно увидеть отдельные машины по всей странице, попробуйте:

select m.Name manufacturer_name,
       sum(case c.Name when 'Ferrari1' then 1 else 0 end) Ferrari1_Count,
       sum(case c.Name when 'Ferrari2' then 1 else 0 end) Ferrari2_Count,
       sum(case c.Name when 'Ferrari3' then 1 else 0 end) Ferrari3_Count
from Manufacturer m
left join Car c 
       on m.PK = c.ManufPK and c.Name in ('Ferrari1','Ferrari2','Ferrari3')
group by m.Name
0 голосов
/ 25 января 2012

Вы также можете попробовать это:

SELECT manuf.Name
     , car1.cnt AS Ferrari1
     , car2.cnt AS Ferrari2
     , car3.cnt AS Ferrari3
FROM 
      Manufacturer AS manuf 
  LEFT JOIN 
      ( SELECT ManufPK, COUNT(*) AS cnt
        FROM Car  
        WHERE Name = 'Ferrari1'
        GROUP BY ManufPK
      ) AS car1 
    ON car1.ManufPK = manuf.PK 
  LEFT JOIN 
      ( SELECT ManufPK, COUNT(*) AS cnt
        FROM Car  
        WHERE Name = 'Ferrari2'
        GROUP BY ManufPK
      ) AS car2 
    ON car2.ManufPK = manuf.PK  
  LEFT JOIN 
      ( SELECT ManufPK, COUNT(*) AS cnt
        FROM Car 
        WHERE Name = 'Ferrari3'
        GROUP BY ManufPK
      ) AS car3 
    ON car3.ManufPK = manuf.PK 
ORDER BY manuf.Name
0 голосов
/ 25 января 2012
SELECT manuf.Name, COUNT(DISTINCT c.Name)
FROM Manufacturer manuf 
LEFT JOIN Car c ON manuf.PK = c.ManufPK
GROUP BY manuf.Name

ИЛИ в зависимости от ваших потребностей

SELECT manuf.Name, c.Name, COUNT(*) Cnt
FROM Manufacturer manuf 
LEFT JOIN Car c ON manuf.PK = c.ManufPK
GROUP BY manuf.Name, c.Name

PS: Ваш вопрос не очень понятен. Предоставить желаемый набор результатов для уточнения ответа

...