我的程序中最后一个select语句的列名无效。我需要获取ThreadTitle
并由列ThreadID
选中。由于F.ForumD
select子句,我无法使用局部变量并进行设置。我只需要获取ThreadID
并将其传递给ThreadTitle
有没有人知道如何做到这一点
SELECT ForumGroup = (
CASE WHEN ParentID IS NOT NULL THEN
(SELECT Title FROM Forums WHERE ForumID = F.ParentID)
ELSE
(SELECT Title FROM Forums WHERE ParentID IS NULL)
END),
Title,
Description,
ThreadCount = (SELECT COUNT(*) FROM Posts P WHERE P.ForumID = F.ForumID),
LastPostBy = (SELECT TOP 1 AddedBy FROM Posts P
WHERE P.ForumID = F.ForumID ORDER BY P.PostID DESC),
LastPostDate = (SELECT TOP 1 AddedDate FROM Posts P
WHERE P.ForumID = F.ForumID ORDER BY P.PostID DESC),
LastPostTitle = (SELECT TOP 1 Title FROM Posts P
WHERE P.ForumID = F.ForumID ORDER BY P.PostID DESC),
ThreadID = CAST(SUBSTRING((SELECT TOP 1 Path_String
FROM Posts P WHERE P.ForumID = F.ForumID ORDER BY P.PostID DESC), 0,
CHARINDEX('/', (SELECT TOP 1 Path_String FROM Posts P
WHERE P.ForumID = F.ForumID ORDER BY P.PostID DESC))) AS INT),
ThreadTitle = (SELECT TOP 1 Title FROM Posts P
WHERE P.PostID = ThreadID ORDER BY P.PostID DESC)
FROM Forums F WHERE ParentID IS NOT NULL
ORDER BY Title
答案 0 :(得分:1)
由于我们没有所有的架构,所以我会对你所拥有的假设以及你应该拥有什么的建议采取一些自由。你应该把它们当作一粒盐,因为它们适合于满足这个查询,我不知道这些建议可能会影响哪些其他查询。
我要猜测基表:
USE tempdb;
GO
CREATE TABLE dbo.Forums
(
ForumID INT PRIMARY KEY,
Title VARCHAR(32),
Description VARCHAR(255),
ParentID INT NULL FOREIGN KEY REFERENCES dbo.Forums(ForumID)
);
CREATE INDEX t ON dbo.Forums(ParentID);
GO
CREATE TABLE dbo.Threads
(
ThreadID INT PRIMARY KEY,
Title VARCHAR(32)
);
GO
CREATE TABLE dbo.Posts
(
PostID INT PRIMARY KEY,
AddedBy VARCHAR(32),
AddedDate DATETIME,
Title VARCHAR(32),
Path_String VARCHAR(255),
ForumID INT FOREIGN KEY REFERENCES dbo.Forums(ForumID)
);
CREATE INDEX f ON dbo.Posts(ForumID, PostID DESC) INCLUDE(AddedBy, AddedDate, Title);
GO
现在,因为Path_String
几乎肯定只写了一次,所以你可以从使这个为持久计算列并为其编制索引中获益匪浅。这样,您只需在插入行时计算昂贵的子字符串,而不是每次运行查询时都要付出代价。
ALTER TABLE dbo.Posts ADD ThreadID AS
CONVERT(INT,SUBSTRING(Path_String, 0, CHARINDEX('/', Path_String)))
PERSISTED FOREIGN KEY REFERENCES dbo.Threads(ThreadID);
CREATE INDEX t ON dbo.Posts(ThreadID);
CREATE INDEX f ON dbo.Posts(ForumID, PostID DESC)
INCLUDE(AddedBy, AddedDate, Title, ThreadID) WITH (DROP_EXISTING = ON);
GO
有了这些东西,您的查询可以重写为:
;WITH p AS
(
SELECT PostID, AddedBy, AddedDate, Title, ForumID, ThreadID,
rn = ROW_NUMBER() OVER (PARTITION BY ForumID ORDER BY PostID DESC),
c = COUNT(*) OVER (PARTITION BY ForumID)
FROM dbo.Posts
)
SELECT
ForumGroup = fp.Title,
f.Title,
f.Description,
ThreadCount = p.c,
LastPostBy = p.AddedBy,
LastPostDate = p.AddedDate,
LastPostTitle = p.Title,
ThreadID = p.ThreadID,
ThreadTitle = t.Title
FROM dbo.Forums AS f
INNER JOIN p ON p.ForumID = f.ForumID
LEFT OUTER JOIN dbo.Threads AS t ON t.ThreadID = p.ThreadID
LEFT OUTER JOIN dbo.Forums AS fp ON fp.ForumID = f.ParentID
WHERE p.rn = 1
AND f.ParentID IS NOT NULL
ORDER BY f.Title;
随意比较执行计划。由于您使用的所有子查询,您将在查询版本中看到更多扫描/搜索/嵌套循环。
当然,如果没有样本数据和期望的结果,我不知道你写的查询(我根据我的答案)是否能得到你需要的结果。但希望你能来到这里并提供更多细节。
答案 1 :(得分:1)
你是否可以尝试在select语句中使用TreadID代替上次选择的TreadID?如果是这样,你可以使用相同的查询并将其替换为TreadID。
SELECT ForumGroup = (
CASE WHEN ParentID IS NOT NULL THEN
(SELECT Title FROM Forums WHERE ForumID = F.ParentID)
ELSE
(SELECT Title FROM Forums WHERE ParentID IS NULL)
END),
Title,
Description,
ThreadCount = (SELECT COUNT(*)
FROM Posts P
WHERE P.ForumID = F.ForumID),
LastPostBy = (SELECT TOP 1 AddedBy
FROM Posts P
WHERE P.ForumID = F.ForumID
ORDER BY P.PostID DESC),
LastPostDate = (SELECT TOP 1 AddedDate
FROM Posts P
WHERE P.ForumID = F.ForumID
ORDER BY P.PostID DESC),
LastPostTitle = (SELECT TOP 1 Title
FROM Posts P
WHERE P.ForumID = F.ForumID
ORDER BY P.PostID DESC),
ThreadID = CAST(SUBSTRING((SELECT TOP 1 Path_String
FROM Posts P
WHERE P.ForumID = F.ForumID
ORDER BY P.PostID DESC), 0, CHARINDEX('/', (SELECT TOP 1 Path_String
FROM Posts P
WHERE P.ForumID = F.ForumID
ORDER BY P.PostID DESC)
)
) AS INT),
ThreadTitle = (SELECT TOP 1 Title
FROM Posts P
WHERE P.PostID = (CAST(SUBSTRING((SELECT TOP 1 Path_String
FROM Posts P
WHERE P.ForumID = F.ForumID
ORDER BY P.PostID DESC), 0, CHARINDEX('/', (SELECT TOP 1 Path_String
FROM Posts P
WHERE P.ForumID = F.ForumID
ORDER BY P.PostID DESC)
)
) AS INT))
ORDER BY P.PostID DESC
)
FROM Forums F WHERE ParentID IS NOT NULL
ORDER BY Title