加入不行,子查询很烂,那怎么办?
Posted
技术标签:
【中文标题】加入不行,子查询很烂,那怎么办?【英文标题】:Join won't do it, and sub query sucks, then what? 【发布时间】:2009-11-22 07:42:37 【问题描述】:首先,很抱歉这个非描述性的标题,我太着急了,所以我想不出一个更好的标题。 第二: 我的数据库的一部分如下图所示: 我在系统上有贡献者,每个人都写给许多来源,而一个来源可以有许多工作的贡献者。用户可以订阅尽可能多的贡献者和尽可能多的来源。现在,我想做的只是检索某个用户的所有文章。这些文章要么来自贡献者,要么来自用户订阅的来源。为方便起见,当用户订阅源时,我只需将所有源贡献者复制到 users_contributors 表。一个棘手的部分是,当我检索用户的文章时,我会检索他的贡献者撰写的所有文章,以及在他关注的来源中发布的所有文章,这些文章在系统上没有有效的贡献者。 (即contributorID 为空)。 我创建了以下查询:
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
)
上述查询的问题在于,它没有返回任何贡献者 ID 为 null 的文章。我知道这是因为贡献者表上的加入。在这种情况下我该怎么办?
-
我应该考虑非规范化吗?
为此查询在每个表上建立索引的探测器字段是什么
快速运行(返回的行集是
大约 10000)?
我需要在这个查询上支持分页,“With ”子句会是 适合我,或者我应该 考虑另一种策略?
提前致谢。 Ps:我使用的是 SQL Server 2008
【问题讨论】:
@7alwagy:你用什么画的表格图? 【参考方案1】: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
如果你需要分页,使用这个(从80
到100
获取页面):
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
【讨论】:
我需要加入 Contributors and Sources 以获得贡献者名称和来源名称。所以.. !! 我不确定工会是否适合我。以下是我的具体需求:我需要按 Articles.OrderDate 对退货记录进行排序,并支持对这些记录进行分页。同样在联合的第二部分,我必须加入源表以获取 SourceName(因为它不会为空)。 @7alwagy :工会应该工作。它在 sql server 2008 中受支持。请参阅technet.microsoft.com/en-us/library/ms180026.aspx。【参考方案2】:你为什么不直接加入
Inner Join Contributors On Articles.ContributorId = Contributors.ContributorID
外连接?
Left Join Contributors On Articles.ContributorId = Contributors.ContributorID
这将导致它返回所有文章,无论是否存在匹配的 SourceID(包括 ContributorID 为空的情况)。
【讨论】:
哎呀,我打错了..它是在 Articles.ContributorID = Contributors.ContributorId 上加入贡献者..我编辑了,请再检查一次!以上是关于加入不行,子查询很烂,那怎么办?的主要内容,如果未能解决你的问题,请参考以下文章