2013-12-20 26 views
3

我有一個相對複雜的SQL查詢運行在data.stackexchange.com上。查詢可以在this link找到(並粘貼在下面)。SQL Server:從查詢返回的動態列

DECLARE @Location varchar(128) = ##Location:string## 
DECLARE @RepLimit int = ##RepLimit:int## 

SELECT Users.DisplayName, 
     Users.Id, 
     Users.WebsiteUrl, 
     Users.Reputation, 
     (
      SELECT COUNT(*) 
      FROM Posts 
      JOIN PostTags ON Posts.ParentId = PostTags.PostId 
      JOIN Tags ON PostTags.TagId = Tags.Id 
      WHERE Posts.PostTypeId = 2 
      AND Tags.Id = 3 -- Javascript 
      AND Posts.OwnerUserId = Users.Id 
     ) AS JavascriptCount, 

     (
      SELECT COUNT(*) 
      FROM Posts 
      JOIN PostTags ON Posts.ParentId = PostTags.PostId 
      JOIN Tags ON PostTags.TagId = Tags.Id 
      WHERE Posts.PostTypeId = 2 
      AND Tags.Id = 5 -- PHP 
      AND Posts.OwnerUserId = Users.Id 
     ) AS PhpCount, 

     (
      SELECT COUNT(*) 
      FROM Posts 
      JOIN PostTags ON Posts.ParentId = PostTags.PostId 
      JOIN Tags ON PostTags.TagId = Tags.Id 
      WHERE Posts.PostTypeId = 2 
      AND Tags.Id = 820 -- jQuery 
      AND Posts.OwnerUserId = Users.Id 
     ) AS jQueryCount, 

     (
      SELECT COUNT(*) 
      FROM Posts 
      JOIN PostTags ON Posts.ParentId = PostTags.PostId 
      JOIN Tags ON PostTags.TagId = Tags.Id 
      WHERE Posts.PostTypeId = 2 
      AND Tags.Id = 21 -- MySQL 
      AND Posts.OwnerUserId = Users.Id 
     ) AS MySqlCount, 

     (
      SELECT COUNT(*) 
      FROM Posts 
      JOIN PostTags ON Posts.ParentId = PostTags.PostId 
      JOIN Tags ON PostTags.TagId = Tags.Id 
      WHERE Posts.PostTypeId = 2 
      AND Tags.Id = 1386 -- Android 
      AND Posts.OwnerUserId = Users.Id 
     ) AS AndroidCount, 

     (
      SELECT COUNT(*) 
      FROM Posts 
      JOIN PostTags ON Posts.ParentId = PostTags.PostId 
      JOIN Tags ON PostTags.TagId = Tags.Id 
      WHERE Posts.PostTypeId = 2 
      AND Tags.Id IN (58338, 81106, 92809, 7003) -- IOS 
      AND Posts.OwnerUserId = Users.Id 
     ) AS IosCount 

FROM Users 

WHERE Users.Reputation > @RepLimit 
AND Users.Location = @Location 

在上面的查詢,幾件事情:

  1. 在data.stackexchange.com,它們生成表單字段,我進入我有DECLARE d頂部的數據(在這種情況下,Location和RepLimit)。
  2. 我正在搜索的標籤(Javascript,iOS,Android,PHP等)都是硬編碼的,每個標籤都使用一個子選擇,這並不像我認爲的那樣高效。

我想更改兩件事,但對SQL Server不夠熟悉,不知道它們是否都可行(也不知道查詢結果是什麼)。這兩個變化是:

  1. 我想優化查詢。現在,我覺得做出六個幾乎相同的子選擇不是實現最終結果的理想方式。
  2. 我希望標籤列表作爲新表單元素中的逗號分隔列表(如頂部的DECLARE d,比如Location和RepLimit)或5個單獨的表單域(限制查詢到多達5個不同的標籤)

有沒有人有類似的查詢(或類似的問題,有實際的列返回查詢是動態的?任何幫助表示讚賞。

回答

1

至於這裏的第一個問題是優化查詢方式:

DECLARE @Location varchar(128) = ##Location:string## 
DECLARE @RepLimit int = ##RepLimit:int## 

SELECT Users.DisplayName, 
     Users.Id, 
     Users.WebsiteUrl, 
     Users.Reputation, 
     sum(case when Tags.Id = 3 then 1 else 0 end) as JavascriptCount, 
     sum(case when Tags.Id = 5 then 1 else 0 end) as PhpCount, 
     sum(case when Tags.Id = 820 then 1 else 0 end) as jQueryCount, 
     sum(case when Tags.Id = 21 then 1 else 0 end) as MySqlCount, 
     sum(case when Tags.Id = 1386 then 1 else 0 end) as AndroidCount, 
     sum(case when Tags.Id IN (58338, 81106, 92809, 7003) then 1 else 0 end) as IosCount 

FROM Users 
    JOIN Posts ON Posts.OwnerUserId = Users.Id 
     JOIN PostTags ON Posts.ParentId = PostTags.PostId 
      JOIN Tags ON PostTags.TagId = Tags.Id 

WHERE Users.Reputation > @RepLimit AND Posts.PostTypeId = 2 
AND Users.Location = @Location 

GROUP BY 
     Users.DisplayName, 
     Users.Id, 
     Users.WebsiteUrl, 
     Users.Reputation 

至於你的第二個問題,我 - 作爲一無所知那些stackexchange形式 - 恐怕我也沒有辦法。但既然你提到逗號分隔列表,你可以利用SQL的CHARINDEX()函數來查找參數中的Tags.Id。這樣的:

case when CHARINDEX(','+convert(varchar,Tags.Id)+',',','[email protected]+',') <> 0 then 1 else 0 end 
+0

在StackExchange上,當您使用'DECLARE'語句時會生成表單,並且當您運行查詢時,表單值會插入到查詢變量中。 StackExchange只運行SQL Server。 –

+0

然後'CHARINDEX'應該是一個明智的解決方案(儘管這忽略了建立在Tags.Id上的索引 - 因此變得效率低得多)。您應該堅持「將查詢限制爲最多5個不同的標籤」。 –