Как вы можете использовать переменные или ссылки в SQL? - PullRequest
1 голос
/ 05 сентября 2010

In следующее :
( выполнение запроса в Stack Exchange Data Explorer , который используетреализация OData в SQL Azure. FAQ говорит, что поддерживает большинство команд TSQL ):

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выпиши:

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

три раза. Как создать переменную или функцию для приведенного выше фрагмента кода ?

Я попытался использовать псевдоним столбца [# Posts], но это не сработало.

Я нашел этих сообщений при повторном использовании вычисленного имени поля для дальнейших вычислений, что похоже на то, что я хочу, но я не могу понять, как его применить.

Ответы [ 2 ]

3 голосов
/ 05 сентября 2010

Поскольку вам нужен счет для каждого пользователя во всей базе данных и, следовательно, для каждого сообщения, просто сделайте это простым способом:

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

Вы можете обнаружить, что это дает тот же план выполнения, что и решение CROSS APPLY, но это может быть только потому, что механизм достаточно умен, чтобы избежать коррелированного подзапроса и переключить его на простой агрегат, как явно указывает этот запрос. Если CROSS APPLY действительно работает лучше, мне интересно узнать почему.

P.S. Я добавил * 1.0, потому что я догадываюсь (не уверен в механизме здесь), что целочисленное деление дает целые числа, и кажется, что вы, вероятно, захотите дроби. Вам придется экспериментировать.

1 голос
/ 05 сентября 2010

Вы можете использовать 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​
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...