开发者

How can you use variables or references in SQL?

开发者 https://www.devze.com 2023-01-14 17:08 出处:网络
In the following: (running a query on the Stack Exchange Data Explorer, which uses an SQL Azure implementation of OData. The FAQ says it supports开发者_如何学运维 most of the TSQL commands):

In the following:

(running a query on the Stack Exchange Data Explorer, which uses an SQL Azure implementation of OData. The FAQ says it supports开发者_如何学运维 most of the TSQL commands):

DECLARE @MinPosts int = ##MinNumberOfPosts##
SELECT
    Id AS [User Link],
    Reputation,
    (SELECT COUNT(*)
    FROM posts
    WHERE posts.OwnerUserId = Users.Id
    ) AS [# Posts],
    Reputation /
    (SELECT COUNT(*)
    FROM posts
    WHERE posts.OwnerUserId = Users.Id
    ) AS [Rep Per Post]
FROM Users
WHERE (SELECT COUNT(*)
    FROM posts
    WHERE posts.OwnerUserId = Users.Id
    ) > @MinPosts
ORDER BY [Rep Per Post] DESC

I write out:

(SELECT COUNT(*)
FROM posts
WHERE posts.OwnerUserId = Users.Id)

three times. How can I create a variable or a function for the above snippet of code?

I tried using the column alias [# Posts], but that didn't work.

I found these posts on reusing a calculated filed name for further calculation, which seems like what I want, but I can't figure out how to apply it.


Since you need the count for every user in the whole database and thus every post, just do it the straightforward way:

SELECT
    Id AS [User Link],
    Reputation,
    Reputation * 1.0 / C.Cnt AS [Rep Per Post]
FROM
   Users U
   INNER JOIN (
      SELECT OwnerUserId, Cnt = Count(*)
      FROM posts
      GROUP BY OwnerUserID
      HAVING Count(*) >= ##MinNumberOfPosts##
   ) C ON U.Id = C.OwnerUserId
ORDER BY [Rep Per Post] DESC

You may find this gives the same execution plan as the CROSS APPLY solution, but that would only be because the engine is clever enough to avoid the correlated subquery and switch it to a simple aggregate as this query explicitly denotes. If CROSS APPLY really performs better I'm quite interested to know why.

P.S. I added * 1.0 because I'm guessing (not sure of the engine here) that integer division yields integers and it seems like you'd probably want fractions. You'll have to experiment.


You can use CROSS APPLY,

DECLARE @MinPosts int = ##MinNumberOfPosts##

SELECT
    Id AS [User Link],
    Reputation,
    counts.[# Posts],
    Reputation / counts.[# Posts] AS [Rep Per Post]
FROM Users
  CROSS APPLY (
    SELECT COUNT(*)
    FROM posts
    WHERE posts.OwnerUserId = Users.Id
  ) counts([# Posts])
WHERE counts.[# Posts] > @MinPosts
ORDER BY [Rep Per Post] DESC​
0

精彩评论

暂无评论...
验证码 换一张
取 消