加入不会这样做,而子查询糟透了,那又怎样?

时间:2009-11-22 07:42:38

标签: tsql sql-server-2008 query-optimization

首先,对于非描述性标题感到抱歉,我太匆忙了,所以我无法想出更好的标题。
第二:
我的数据库的一部分看起来像下图:
alt text 我在系统上有贡献者,每个人都写了很多来源,而且一个来源可以有许多工作贡献者。用户可以根据自己的喜好订阅尽可能多的贡献者,也可以根据需要订阅尽可能多的贡献者。现在,我想要做的只是为特定用户检索所有文章。这些文章要么通过贡献者来源,要么来自用户订阅的来源。为了方便起见,当用户订阅源时,我只需将所有源贡献者复制到users_contributors表。一个棘手的部分,当我检索用户的文章时,我检索了他的贡献者所写的所有文章,以及他所遵循的来源中发布的所有文章,其中这些文章在系统上没有有效的贡献者。 (I.E contributorID为null)。
我创建了以下查询:

 Select Articles.ArticleID, Articles.ContributorId, Contributors.Name, 
    Sources.Name, Articles.ArticleTitle
From Articles 
            Inner Join Contributors On Articles.ContributorId = Contributors.ContributorId
            Inner Join Sources On Articles.SourceId = Sources.SourceID          
Where Articles.ContributorId in (
    Select ContributorId from Users_Contributors
    Where UserID = 3
    )
    OR (

        Articles.SourceId in (
            Select SourceId from Users_Sources
            Where UserID = 3
            )

            and 
            Articles.ContributorId is null
    )

上述查询的问题在于,它不会返回任何带有contributorID null的文章。我理解这是因为贡献者表上的连接。在这种情况下我该怎么办?

  1. 我应该考虑非规范化吗?
  2. 在此查询的每个表上索引的prober字段是什么 跑得快(Rowset返回的是 大约10000)?
  3. 我需要支持对此查询的分页,将“With {}”子句 适合我,或者我应该 考虑另一种策略?


    提前致谢。
    Ps:我正在使用SQL Server 2008

2 个答案:

答案 0 :(得分:4)

SELECT  a.*, s.Name AS SourceName, NULL AS ContributorName
FROM    User_Sources us
JOIN    Articles a
ON      a.SourceID = us.SourceID
JOIN    Source s
ON      s.SourceID = us.SourceID
WHERE   us.UserID = 3
        AND a.ContributorID IS NULL
UNION
SELECT  a.*, s.Name AS SourceName, c.Name AS ContributorName
FROM    User_Contributor uc
JOIN    Articles a
ON      a.ContributorID = uc.ContributorID
JOIN    Contirbutors c
ON      c.ContributorID = uc.ContributorID
JOIN    Sources s
ON      s.SourceID = a.SourceID
WHERE   uc.UserID = 3

如果您需要分页,请使用此功能(从80100获取页面):

WITH    q AS (
        SELECT  TOP 100 
                a.*, s.Name AS SourceName, NULL AS ContributorName
        FROM    User_Sources us
        JOIN    Articles a
        ON      a.SourceID = us.SourceID
        JOIN    Source s
        ON      s.SourceID = us.SourceID
        WHERE   us.UserID = 3
                AND a.ContributorID IS NULL
        ORDER BY
                OrderDate
        UNION
        SELECT  TOP 100
                a.*, s.Name AS SourceName, c.Name AS ContributorName
        FROM    User_Contributor uc
        JOIN    Articles a
        ON      a.ContributorID = uc.ContributorID
        JOIN    Contirbutors c
        ON      c.ContributorID = uc.ContributorID
        JOIN    Sources s
        ON      s.SourceID = a.SourceID
        WHERE   uc.UserID = 3
        ORDER BY
                OrderDate
        ),
        page AS
        (
        SELECT  TOP 100 *, ROW_NUMBER() OVER (ORDER BY OrderDate) AS rn
        FROM    q
        )
SELECT  *
FROM    page
WHERE   rn >= 80

答案 1 :(得分:2)

为什么不直接加入

Inner Join Contributors On Articles.ContributorId = Contributors.ContributorID

外部联接?

Left Join Contributors On Articles.ContributorId = Contributors.ContributorID

这将导致它返回所有文章,无论是否存在匹配的SourceID(包括ContributorID为null的情况)。