2

我以前从未使用过 TSQL,但我决定无论如何我都想在 SO数据转储中四处寻找。所以这可能是一个菜鸟问题。我确实尝试搜索答案,但我不知道我正在尝试做什么的技术术语,并且如果您没有正确的关键字,搜索只会很好。

我的目标是找出有多少问题得分为 0,多少问题得分为 1,多少问题得分为 2,等等。我可以写一个查询来找出那些个人计数,没问题。不过,我希望能够运行包含循环的查询。这是我目前使用的:

DECLARE @counter int
SET @counter = 0
WHILE @counter < 3
BEGIN
    SELECT
        COUNT(*)
    FROM
        Posts
    WHERE
        PostTypeId = 1
    AND
        Score = @counter

    SET @counter = @counter + 1
END

编辑:最终目标是从 [0, 3] 扩展到 [-100, 1000] 或解决所有现有问题所需的任何东西)显然,我的问题是我在循环的每个循环中都抓住了计数然后什么也不做。@counter目前,我得到的结果只是最初设置的计数;迭代次数无关紧要。是否可以将结果存储在某处,然后显示为:

+-------+--------------------------------+
| 分数 | NumberOfQuestionsWithThatScore |
+-------+--------------------------------+
| -10 | 111 |
+-------+--------------------------------+
| -9 | 0 |
+-------+--------------------------------+
| -8 | 248 |
+-------+--------------------------------+
| ... | ... |
+-------+--------------------------------+

编辑:任何合理清晰的显示都可以,上表只是一个示例;编辑 2:修改了表格的设计以消除持续的混乱)

如果是这样,这叫什么,它是如何完成的?

4

3 回答 3

6

实际上,您可以一次完成此操作...

SELECT COUNT(*) AS Total, MAX(Score) AS Score
FROM Posts
WHERE PostTypeId = 1 And Score <= 3
Group By Score

那应该给你一个很好的桌子,比如:

Score   Total
0       2490
1       2904
2       2110

痛,即兴表演,而不是现在在数据库面前验证语法。查找“分组依据”以获得更好的主意。

正如@OMG Ponies 指出的那样,这并没有像您最初那样进行旋转。如果你想有一个单列,你需要使用 SELECT 和 SUM 来做到这一点。

于 2010-09-16T15:52:20.443 回答
6

您列出的输出是一个标准的数据透视查询,将行转换为列数据:

SELECT SUM(CASE WHEN p.score = 0 THEN 1 ELSE 0 END) AS ScoreOfZero,
       SUM(CASE WHEN p.score = 1 THEN 1 ELSE 0 END) AS ScoreOfOne,
       SUM(CASE WHEN p.score = 2 THEN 1 ELSE 0 END) AS ScoreOfTwo
  FROM POSTS p
于 2010-09-16T15:54:42.960 回答
1

示例 1:这只是基于原始方法的充实解决方案,但为从最小值到最大值的每个分数计数提供了一行,包括零计数分数。

--Posts per score, with zeros.

declare @minScore int
declare @maxScore int
declare @current int
declare @postType int

set @postType = 1

set @minScore = (select MIN(Score) from Posts where PostTypeId = @postType)
set @maxScore = (select MAX(Score) from Posts where PostTypeId = @postType)

set @current = @minScore

create table #myTemp (Score int, PostsCount int) 

insert into #myTemp
select Score, count(*) from Posts group by Score

while @current < @maxScore
begin
  insert into #myTemp
  select @current, 0
    where not exists (select 1 from #myTemp where Score = @current and PostTypeId = @postType)
  set @current = @current + 1
end

select * from #myTemp order by Score
​

示例 2:一个俗气的动态 SQL 方法,以 Columns 作为分数,每列是一个子查询。免责声明:SEDE 似乎执行了这一切,但您没有得到结果。如果您改为select @dynSQL在最后运行它,您将获得数据。

-- Dynamic SQL count of all posts for a score

declare @minScore int
declare @maxScore int
declare @current int
declare @postType int
declare @dynSQL nvarchar(MAX)

set @postType = 1

set @minScore = (select MIN(Score) from Posts where PostTypeId = @postType)
set @maxScore = (select MAX(Score) from Posts where PostTypeId = @postType)

set @current = @minScore

set @dynSQL = 'select '

while @current <= @maxScore
begin
    set @dynSQL = @dynSQL 
                  + '(select count(*) from Posts where PostTypeId = ' 
                  + convert(varchar,@postType) + ' and Score = ' 
                  + convert(varchar,@current) + ') as Score_'
                  + CASE WHEN @current < 0 THEN 'Negative_' 
                              + convert(varchar,ABS(@current)) 
                         ELSE convert(varchar,@current)
                         END
    if @current < @maxScore set @dynSQL = @dynSQL + ', '
    set @current = @current + 1
end

exec(@dynSQL)
​
于 2010-09-16T18:31:10.580 回答