按字段分割的频率分布

sri*_*amn 5 sql-server stored-procedures statistics view

一些背景: 我有一个样本人口数据文件。数据文件中的每条记录都有一个频率权重(FIELD NAME: wgt),指示需要复制多少次记录才能获得真正的总体。数据在 Microsoft SQL 2008 R2 中设置。生成权重的频率分布以查看某种特定类型的记录是否以任何方式过度表示通常是一种很好的做法 - 从而帮助识别趋势/异常值。这个任务在 SQL 中很简单:

SELECT wgt, COUNT(*) FROM tablename 
GROUP BY wgt
Run Code Online (Sandbox Code Playgroud)

挑战: 我想根据其他值进一步分离这些频率。假设不同家庭规模的权重频率分布。实现此目的的一种方法是在上述语句中使用不同的 where 条件:

SELECT wgt, COUNT(*) FROM tablename 
WHERE household_size=x --x being the desired segment
GROUP BY wgt
Run Code Online (Sandbox Code Playgroud)

但是有没有办法用所有不同的段创建一个表?像这样的东西:

WGT |   SIZE1       SIZE2       SIZE3       SIZE4 
--------------------------------------------------
1   |    2,034      1,025       502         234 
2   |    215        253         142         23 
3   |    31         25          21          34 
4   |    7          1           3           7 
5   |    5          NULL        2           5 
6   |    1          1           NULL        NULL 
7   |    NULL       1           NULL        NULL 
Run Code Online (Sandbox Code Playgroud)

我正在寻找一个更好的解决方案:一个存储过程,我可以在其中指定变量(比如家庭规模或家庭收入),并且代码应该能够为该变量的所有不同值生成单独的频率分布作为视图/表。

大家有什么想法吗?

Jos*_*ira 3

对于第一个挑战,您是否正在寻找这样的东西?

SELECT wgt, SUM(Case when household_size=1 then 1 else 0 end) AS SIZE1
    , SUM(Case when household_size=2 then 1 else 0 end) AS SIZE2
    , SUM(Case when household_size=3 then 1 else 0 end) AS SIZE3
    , SUM(Case when household_size=4 then 1 else 0 end) AS SIZE4
FROM tablename
GROUP BY wgt
Run Code Online (Sandbox Code Playgroud)

现在,迎接更高级的挑战,其中 @column 将是您的 sp 参数:

DECLARE @column VARCHAR(100);
SET @column = 'household_size';
DECLARE @main_SQL VARCHAR(4000);

SET @main_SQL =
    'DECLARE dynamic_cursor CURSOR FOR 
    SELECT DISTINCT ' + @column + '
    FROM tablename 
    ORDER BY ' + @column + ' 

    --Now we will be using a cursor to iterate over 
    DECLARE @value INT; 
    OPEN dynamic_cursor 
    FETCH NEXT FROM dynamic_cursor INTO @value 

    DECLARE @sql VARCHAR(2000); 
    SET @sql = ''SELECT wgt''; 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
        SET @sql = @sql + '', SUM(Case when ' + @column + '='' + CAST(@value AS VARCHAR) + '' then 1 else 0 end) AS SIZE'' + CAST(@value AS VARCHAR) 
        FETCH NEXT FROM dynamic_cursor INTO @value 
    END 
    SET @sql = @sql + '' FROM tablename GROUP BY wgt'' 

    close dynamic_cursor 
    DEALLOCATE dynamic_cursor 

    EXEC(@sql) '

EXEC(@main_SQL)
Run Code Online (Sandbox Code Playgroud)

这部分选择接收到游标中的表名列的不同值

DECLARE dynamic_cursor CURSOR FOR 
SELECT DISTINCT ' + @column + '
FROM tablename 
ORDER BY ' + @column + ' 
Run Code Online (Sandbox Code Playgroud)

接下来,我们将迭代不同的值以动态构建一个查询,该查询看起来就像我的文章顶部的查询一样,因此这是它的基础:
开始选择:

SET @sql = ''SELECT wgt''
Run Code Online (Sandbox Code Playgroud)

迭代部分动态地将连续添加, SUM(Case when household_size=n then 1 else 0 end) AS SIZEn到选择中(请注意,@value 将是我们在光标中选择的不同值):

SET @sql = @sql + '', SUM(Case when ' + @column + '='' + CAST(@value AS VARCHAR) + '' then 1 else 0 end) AS SIZE'' + CAST(@value AS VARCHAR)
Run Code Online (Sandbox Code Playgroud)

完成选择:

SET @sql = @sql + '' FROM tablename GROUP BY wgt''
Run Code Online (Sandbox Code Playgroud)