编写以下SQL查询的更有效方法

时间:2017-12-11 13:23:08

标签: sql sql-server optimization query-optimization

我正在编写一个查询,以返回新闻门户主页的文章列表。 要求如下。

需要在主页上的每个类别需要按照以下标准显示5篇文章。

每个类别都需要有一篇文章作为该类别的主要新闻,其次是4篇当时最受欢迎的新闻。 如果没有关于类别集的第一个新闻,则显示5个最受欢迎的内容。

我写了一个SQL函数,它有CategoryID参数和另一个调用该函数N Times的SQL过程。

是否有更有效的方法来编写此查询?

功能

CREATE FUNCTION [dbo].[Fn_FetchHomepageCategory] 
(   
    -- Add the parameters for the function here
    @categoryId int

)
RETURNS @ArticlesToReturn TABLE 
                      ( Id int, 
                        Title nvarchar(500),
                        Slug nvarchar(500),
                        Summary nvarchar(1500),
                        IsCategoryFirst bit,
                        RootCategoryId int,
                        RootCategory nvarchar(500),
                        OldFacebookCommentsUrl nvarchar(500),
                        Icon nvarchar(500),
                        TopicName nvarchar(500),
                        MainArticlePhoto nvarchar(500),
                        FrontPagePhoto nvarchar(500),
                        PublishDate datetime

                      )  
AS
BEGIN


    -- select category first news if any
    INSERT INTO @ArticlesToReturn
    SELECT TOP 1
    ART.Id, ART.Title, ART.InitialTitle, ART.Summary,ART.IsCategoryFirst,
    ART.RootCategoryId, CAT.Name, ART.OldFacebookCommentsUrl, ICO.CssClass,
    ART.TopicName, ART.MainArticlePhoto, ART.FrontPagePhoto, ART.PublishDate
    FROM Articles ART WITH (NOLOCK)
    INNER JOIN ArticleViewCountSum AVS WITH (NOLOCK) ON AVS.ArticleId = ART.Id 
    INNER JOIN Categories CAT WITH (NOLOCK) ON CAT.Id = ART.RootCategoryId 
    LEFT JOIN ArticleIcons ICO WITH (NOLOCK) ON ICO.Id = ART.IconId
    WHERE ART.RootCategoryId = @categoryId
    AND ART.PublishDate < GETDATE() 
    AND ART.Active = 1
    AND IsCategoryFirst = 1

    -- select 5 most popular by coefficient
    INSERT INTO @ArticlesToReturn
    SELECT TOP 5 
    ART.Id, ART.Title, ART.InitialTitle, ART.Summary,ART.IsCategoryFirst,
    ART.RootCategoryId, CAT.Name, ART.OldFacebookCommentsUrl, ICO.CssClass,
    ART.TopicName, ART.MainArticlePhoto, ART.FrontPagePhoto, ART.PublishDate
    FROM Articles ART WITH (NOLOCK)
    INNER JOIN ArticleViewCountSum AVS WITH (NOLOCK) ON AVS.ArticleId = ART.Id 
    INNER JOIN Categories CAT WITH (NOLOCK) ON CAT.Id = ART.RootCategoryId 
    LEFT JOIN ArticleIcons ICO WITH (NOLOCK) ON ICO.Id = ART.IconId
    WHERE ART.RootCategoryId = @categoryId
    AND ART.PublishDate < GETDATE() 
    AND ART.Active = 1

    ORDER BY  ART.Coefficient  DESC


    RETURN 

END

存储过程

CREATE PROCEDURE [dbo].[Fetch_HomePageArticles]

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    DECLARE @dateNow datetime = GETDATE();

    -- first main news
    SELECT TOP 1 * FROM Articles 
    WHERE IsFirst = 1 AND PublishDate < @dateNow


    --TODO: featured
    SELECT TOP 10 * From Featured 
    WHERE PublishDate < @dateNow AND Active = 1 
    ORDER BY PublishDate DESC


    SELECT TOP 5 * FROM Fn_FetchHomepageCategory(3) 
    SELECT TOP 5 * FROM Fn_FetchHomepageCategory(150) 
    SELECT TOP 5 * FROM Fn_FetchHomepageCategory(1523) 
    SELECT TOP 5 * FROM Fn_FetchHomepageCategory(1509) 
    SELECT TOP 5 * FROM Fn_FetchHomepageCategory(1569) 
    SELECT TOP 5 * FROM Fn_FetchHomepageCategory(1545) 
    SELECT TOP 5 * FROM Fn_FetchHomepageCategory(1548) 
    SELECT TOP 5 * FROM Fn_FetchHomepageCategory(67)

END

我尝试修改函数只有一个SELECT并包含Order BY IsFirstCategory DESC,但查询运行速度要慢得多。

1 个答案:

答案 0 :(得分:0)

一个潜在的改进是将Fn_FetchHomepageCategory函数中的两个SELECT子句合并为一个单个查询,方法是添加一个新的Coefficient参数:

SELECT 
    TOP 5 ART.Id, 
    ART.Title, 
    ART.InitialTitle, 
    ART.Summary, 
    ART.IsCategoryFirst, 
    ART.RootCategoryId, 
    CAT.Name, 
    ART.OldFacebookCommentsUrl, 
    ICO.CssClass, 
    ART.TopicName, 
    ART.MainArticlePhoto, 
    ART.FrontPagePhoto, 
    ART.PublishDate
 FROM 
  Articles ART WITH (NOLOCK) 
  INNER JOIN ArticleViewCountSum AVS WITH (NOLOCK) ON AVS.ArticleId = ART.Id 
  INNER JOIN Categories CAT WITH (NOLOCK) ON CAT.Id = ART.RootCategoryId 
  LEFT JOIN ArticleIcons ICO WITH (NOLOCK) ON ICO.Id = ART.IconId 
WHERE 
  ART.RootCategoryId = @categoryId 
  AND ART.PublishDate < GETDATE() 
  AND ART.Active = 1 
ORDER BY 
  CASE IsCategoryFirst
  WHEN 1    THEN 1000000
  ELSE  ART.Coefficient 
  END DESC

您可以用另一个大号替换1000000。唯一的一点是为具有IsCategoryFirst = 1的帖子分配最高的协同效率分数。 请注意,只有当您只有一个IsCategoryFirst = 1的帖子时,它才能正常工作。