一部の背景:サンプルの母集団データファイルがあります。データファイルの各レコードには、実際の母集団を取得するためにレコードを複製する必要がある回数を示す頻度の重み(フィールド名:wgt
)があります。データはMicrosoft SQL 2008 R2で設定されています。通常、重みの頻度分布を生成して、特定のタイプのレコードが何らかの方法で過剰に表現されているかどうかを確認することをお勧めします。したがって、傾向/外れ値を特定するのに役立ちます。このタスクはSQLでは簡単です。
SELECT wgt, COUNT(*) FROM tablename
GROUP BY wgt
Challenge:これらの頻度を他の値に基づいてさらに分離したい。世帯のサイズごとの重みの度数分布を考えてみましょう。これを実現する1つの方法は、上記のステートメントで異なるwhere条件を使用することです。
SELECT wgt, COUNT(*) FROM tablename
WHERE household_size=x --x being the desired segment
GROUP BY wgt
しかし、すべての異なるセグメントを持つ単一のテーブルを作成する方法はありますか?このようなもの:
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
私が探しているより洗練されたソリューション:変数(たとえば、世帯のサイズや世帯収入)を指定するだけのストアドプロシージャであり、コードはそのすべての個別の値に対して個別の度数分布を生成できるはずですビュー/テーブルとしての変数。
考えている人はいますか?
最初の挑戦として、このようなものを探していますか?
_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
_
ここで、@ 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)
_
この部分は、カーソルに受け取ったテーブル名の列の個別の値を選択します
_DECLARE dynamic_cursor CURSOR FOR
SELECT DISTINCT ' + @column + '
FROM tablename
ORDER BY ' + @column + '
_
次に、個別の値を反復処理して、投稿の上部にあるクエリと同じように見えるクエリを動的に構築します。そのため、以下がその基礎です。
選択を開始します:
_SET @sql = ''SELECT wgt''
_
連続する, 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)
_
選択を終了します。
_SET @sql = @sql + '' FROM tablename GROUP BY wgt''
_
PIVOT
演算子を使用する必要があります:
SELECT wgt,
[SIZE1] as Size_1, [SIZE2] as Size_2, [SIZE3] as Size_3, [SIZE4] as Size_4
FROM
(select wgt, household_size from tablename)
PIVOT (
COUNT (household_size)
FOR household_size in ([SIZE1], [SIZE2] , [SIZE3] , [SIZE4])
)
ORDER BY wgt
[SIZE1], [SIZE2] , [SIZE3] , [SIZE4]
-列として表示するhousehold_size
列の値です。
この列のフィルターでhousehold_size
の入力値を使用できるため、1つの集計列(全体で2列)を生成するストアドプロシージャははるかに簡単です。 WHERE
句とHAVING
句を使用したクエリは、うまく機能します。