Самый эффективный способ получить количество записей из связанной таблицы? - PullRequest
0 голосов
/ 04 декабря 2009

У меня есть хранимая процедура, в которой есть оператор select:

select 
    (select Count(FaqId) from faq_read_stats where faqid = Faq.Id) as ReadCount,
    Faq.*
from Faq 
where Faq.Show = 1 and Faq.Active = 1

Это дает мне результаты, которые я хочу, но кажется, что наличие счетчика ad-hoc select там может быть не оптимизировано для SQL Server.

Я попытался выполнить внутреннее соединение с таблицей faq_read_stats, но это не дало правильных результатов (из-за этого отсутствовали записи faq, в которых не было записи в faq_read_stats, в то время как sql, который я набрал выше, правильно показывает счетчик 0 для них).

Есть ли более эффективный способ получения этих данных?

Ответы [ 4 ]

4 голосов
/ 04 декабря 2009

Вам нужно попробовать его для сравнения, но есть альтернатива:

SELECT ISNULL(x.ReadCount, 0) AS ReadCount, f.*
FROM Faq f
    LEFT JOIN
    (
        SELECT faqid, COUNT(faqid) AS ReadCount
        FROM faq_read_stats
        GROUP BY faqid
    ) x ON f.id = x.faqid
WHERE f.Show = 1 AND f.Active = 1
1 голос
/ 04 декабря 2009

Вместо использования внутреннего соединения используйте левое внешнее соединение:

SELECT
     COUNT(*) AS read_count,
     FAQ.col_1,
     FAQ.col_2,
     FAQ.col_3,
     ...
FROM
     FAQ
LEFT OUTER JOIN Faq_Read_Stats FRS ON
     FRS.faq_id = FAQ.faq_id
WHERE
     FAQ.show = 1 AND
     FAQ.active = 1
GROUP BY
     FAQ.col_1,
     FAQ.col_2,
     FAQ.col_3,
     ...
0 голосов
/ 05 декабря 2009

При настройке запросов я всегда учитываю подход «разделяй, чтобы победить».

Я бы поспорил с кодом ниже, чтобы получить лучшие результаты:

select FaqID, count(*) as ReadCount
into #cnt
from faq_read_stats
group by FaqID
go

select 
  #cnt.ReadCount,
  Faq.*
from
  Faq
    left outer join #cnt
    on cnt.FaqID = Faq.FaqID
where Faq.Show = 1 and Faq.Active = 1
go

drop table #cnt
go

Этот подход делает его более «читаемым человеком» и не вводит «ложно оптимальных» планов.

0 голосов
/ 04 декабря 2009

Хотелось бы что-нибудь подобное или это то, что вы уже пробовали?

SELECT SUM(CASE WHEN (faq_read_stats.FaqId = Faq.Id) THEN 1 ELSE 0 END) AS ReadCount, Faq.*
FROM Faq INNER JOIN faq_read_stats ON faq_read_stats.FaqId = Faq.Id
WHERE Faq.Show = 1 and Faq.Active = 1

Джеймс

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...