Оптимизация SQL-запросов для расчета коэффициента - PullRequest
2 голосов
/ 17 февраля 2012

У меня есть 2 таблицы (это только часть столбцов таблицы, которые необходимы для этого запроса):

Items: Id int, OwnerId int
ItemsRelations: RelationId int, ItemId Int (FK Items(Id))

Для каждого OwnerId мне нужно вычислить результат функции отношения: Количество пользовательских элементов, которые имеют ссылки на ItemsRelationstable / count всех пользовательских элементов.

Я написал этот запрос, но он медленный и неоптимальный. Есть ли более простой и быстрый способ сделать это?

SELECT OwnerId , (100 * SUM(HasRelation))/COUNT(Id) AS Ratio
FROM (
  SELECT 
    oi.OwnerId,
    oi.Id,
    (CASE WHEN SUM(ir.Id) > 0 THEN 1 ELSE 0 END) HasRelation
  FROM Items AS oi
  LEFT JOIN ItemsRelations AS ir ON ir.ItemId  = oi.Id
  GROUP BY oi.Id, oi.OwnerId) tempTab 
GROUP BY OwnerId 

Ответы [ 2 ]

2 голосов
/ 17 февраля 2012
SELECT oi.OwnerId, Ratio = 1.0 * Count(ir.ItemId) / Count(*)
FROM Items AS oi
LEFT JOIN ItemsRelations AS ir ON ir.ItemId  = oi.Id
GROUP BY oi.OwnerId

Примечания:

  • 1.0 добавлено для преобразования выражения в результат с плавающей точкой
  • Count (ir.ItemId) пропускает NULLS, поэтому он учитывает только те из них, которые имеют отношение

Если от Items до ItemsRelations один-ко-многим, вам, возможно, потребуется ОПРЕДЕЛИТЬ его

SELECT oi.OwnerId, Ratio = 1.0 * Count(DISTINCT ir.ItemId) / Count(DISTINCT oi.Id)
FROM Items AS oi
LEFT JOIN ItemsRelations AS ir ON ir.ItemId  = oi.Id
GROUP BY oi.OwnerId
0 голосов
/ 17 февраля 2012

Я думаю, что это должно сработать:

select i.OwnerId,
       case when count(i.Id) > 0 then count(r.Id)/count(i.Id) else 0 end as Ratio
from Items i
left join ItemsRelations r on r.ItemId = i.Id
group by i.Id, i.OwnerId
...