3

data.stackexchange.com に対してかなり複雑な SQL クエリを実行しています。クエリはこのリンクにあります (下に貼り付けてあります)。

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、上部にあるデータ (この場合は Location と RepLimit) を入力するためのフォーム フィールドが生成されます。
  2. 私が探しているタグ (Javascript、iOS、Android、PHP など) はハードコーディングされており、それぞれサブセレクトを使用していますが、これは思ったほど効率的ではありません。

私は2つのことを変更したいのですが、SQL Serverに精通していないため、両方が実行可能かどうかを知ることができません(また、必要な結果を見つけるために正確に何を照会すればよいかもわかりません)。2 つの変更点は次のとおりです。

  1. クエリを最適化したい。現在、6 つのほぼ同一のサブセレクトを作成することは、最終結果を達成するための理想的な方法ではないと感じています。
  2. タグのリストを、新しいフォーム要素のコンマ区切りリスト ( DECLARELocation や RepLimit のように上部にある)、または 5 つの個別のフォーム フィールド (クエリを最大 5 つに制限) として提供したいと考えています。別のタグ)

同様のクエリを経験した人はいますか (または、クエリによって返される実際の列を動的にするという同様の問題がありますか?)。どんな助けでも大歓迎です。

4

1 に答える 1

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

2 番目の質問については、stackexchange フォームについて何も知らないので、どうしようもありません。ただし、カンマ区切りのリストについて言及しているため、SQL の CHARINDEX() 関数を使用して、パラメーターで Tags.Id を検索できます。次のように:

case when CHARINDEX(','+convert(varchar,Tags.Id)+',',','+@List1+',') <> 0 then 1 else 0 end 
于 2013-12-20T19:58:39.323 に答える