2012-02-10 29 views
-1

我的過程中的最後一個選擇語句中有一個錯誤無效的列名稱。我需要得到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 
+2

這與C#或ASP.NET有什麼關係?這是一個純粹的[t-sql](http://stackoverflow.com/questions/tagged/tsql)問題。 – 2012-02-10 23:12:02

+1

你可以發佈兩個創建表語句嗎?如果您還可以將一些插入示例與預期結果一起使用,那將非常有幫助。 – 2012-02-10 23:23:29

+0

帖子標題和帖子標題有什麼區別?有沒有一個線程表,你忘了提及/參考? – 2012-02-10 23:26:09

回答

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

您是否試圖使用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 
+0

我不認爲ThreadTitle和PostTitle是相同的(換句話說,ThreadTitle不應該來自Posts表)。 – 2012-02-11 00:30:29

+0

我不是說..他的查詢有.. ..我不知道dataschema ..我根據我從@ KDM的問題所瞭解的內容給出了我的答案。 – AJP 2012-02-11 00:37:16