-1

このフィドルを参照してください。各質問がカテゴリに分類される質問の表があり、各カテゴリのユーザー平均を見つける必要があります。うまく機能していると思いますが、各ユーザーの平均に含まれる回答の総数を示す合計を追加したかったのです。各ユーザーの質問の総数を実際に返すには、where 句に何を入力すればよいかわかりません。ユーザーID、QID、または選択を含めても、天文学的な数字が得られます。

クエリ SQL:

DECLARE @tblTmpCatStats TABLE (userid NVARCHAR(10),cat1_mean FLOAT,cat2_mean FLOAT,cat3_mean FLOAT,cat4_mean FLOAT,N FLOAT)
INSERT INTO @tblTmpCatStats SELECT d.userid
    ,AVG(CAST(c1.choice AS FLOAT))
    ,AVG(CAST(c2.choice AS FLOAT))
    ,AVG(CAST(c3.choice AS FLOAT))
    ,AVG(CAST(c4.choice AS FLOAT))
    ,COUNT(d.userid)
FROM tblTmpDemographics d
JOIN tblTmpDemographics c1 ON d.userid = c1.userid
JOIN tblTmpDemographics c2 ON d.userid = c2.userid
JOIN tblTmpDemographics c3 ON d.userid = c3.userid
JOIN tblTmpDemographics c4 ON d.userid = c4.userid
WHERE c1.QID IN ('1','5')
AND c2.QID IN ('2','6')
AND c3.QID IN ('3','7')
AND c4.QID IN ('4','8')
GROUP BY d.userid
SELECT * FROM @tblTmpCatStats

AVG に含まれる選択肢の総数を N に等しくしようとしています。

セットアップ SQL:

CREATE TABLE tblTmpDemographics (userid NVARCHAR(10),QID INT,choice NVARCHAR(1000))
INSERT INTO tblTmpDemographics (userid,QID,choice)
SELECT 'user1',1,'5' UNION ALL SELECT 'user1',2,'3' UNION ALL
SELECT 'user1',3,'4' UNION ALL SELECT 'user1',4,'5' UNION ALL
SELECT 'user1',5,'5' UNION ALL SELECT 'user1',6,'3' UNION ALL
SELECT 'user1',7,'4' UNION ALL SELECT 'user1',8,'5' UNION ALL

SELECT 'user2',1,'3' UNION ALL SELECT 'user2',2,'2' UNION ALL
SELECT 'user2',3,'3' UNION ALL SELECT 'user2',4,'5' UNION ALL
SELECT 'user2',5,'3' UNION ALL SELECT 'user2',6,'2' UNION ALL
SELECT 'user2',7,'3' UNION ALL SELECT 'user2',8,'5' UNION ALL

SELECT 'user3',1,'2' UNION ALL SELECT 'user3',2,'1' UNION ALL
SELECT 'user3',3,'5' UNION ALL SELECT 'user3',4,'5' UNION ALL
SELECT 'user3',5,'2' UNION ALL SELECT 'user3',6,'1' UNION ALL
SELECT 'user3',7,'5' UNION ALL SELECT 'user3',8,'5' UNION ALL

SELECT 'user4',1,'4' UNION ALL SELECT 'user4',2,'3' UNION ALL
SELECT 'user4',3,'3' UNION ALL SELECT 'user4',4,'5' UNION ALL
SELECT 'user4',5,'4' UNION ALL SELECT 'user4',6,'3' UNION ALL
SELECT 'user4',7,'3' UNION ALL SELECT 'user4',8,'5' GO

8 ではなく 128 を返すのはなぜですか?

4

4 に答える 4

2

結果を取得するために選択した方法では、すべての結合がさらにフィルター処理されていても、行ごとに複数の一致が発生する可能性があり (最終的にはそうなる場合もあります)、正しいカウントが得られません。次に、最終的に集約される中間結果セットでミニデカルト積を生成します。

@bluefeet による提案は、カウントが個別に計算されるため機能しますが、それでも一般的なデカルト積の影響は修正されません。カウント合計ではなく、単に平均であるため、平均が正しいことがわかります。基本的に、それらはもちろん、合計をカウントで割ったものであり、両方のオペランドが同じように因数分解されるため、デカルト積の影響に関係なく、平均は正しくなります。ただし、値に対して SUM または COUNT を試すと、間違った結果が再び表示されます。choice

代わりに、次のように条件付き集計を使用できます。

SELECT
  userid,
  cat1_mean = AVG(CASE WHEN QID IN (1, 5) THEN CAST(choice AS float) END),
  cat2_mean = AVG(CASE WHEN QID IN (2, 6) THEN CAST(choice AS float) END),
  cat3_mean = AVG(CASE WHEN QID IN (3, 7) THEN CAST(choice AS float) END),
  cat4_mean = AVG(CASE WHEN QID IN (4, 8) THEN CAST(choice AS float) END),
  N = COUNT(*)
FROM tblTmpDemographics
GROUP BY userid
;

または、次のように SQL ServerのPIVOT機能を使用することもできます。

SELECT
  userid,
  cat1_mean,
  cat2_mean,
  cat3_mean,
  cat4_mean,
  N
FROM (
  SELECT
    userid,
    choice = CAST(choice AS float),
    QuestionGroup = CASE
      WHEN QID IN (1, 5) THEN 'cat1_mean'
      WHEN QID IN (2, 6) THEN 'cat2_mean'
      WHEN QID IN (3, 7) THEN 'cat3_mean'
      WHEN QID IN (4, 8) THEN 'cat4_mean'
    END,
    N = COUNT(*) OVER (PARTITION BY userid)
  FROM tblTmpDemographics
) s
PIVOT (
  AVG(choice) FOR QuestionGroup IN (
    cat1_mean,
    cat2_mean,
    cat3_mean,
    cat4_mean
  )
) p
;

またはこのように(前と同じですが、共通のテーブル式を使用します):

WITH marked AS (
  SELECT
    userid,
    choice = CAST(choice AS float),
    QuestionGroup = CASE
      WHEN QID IN (1, 5) THEN 'cat1_mean'
      WHEN QID IN (2, 6) THEN 'cat2_mean'
      WHEN QID IN (3, 7) THEN 'cat3_mean'
      WHEN QID IN (4, 8) THEN 'cat4_mean'
    END,
    N = COUNT(*) OVER (PARTITION BY userid)
  FROM tblTmpDemographics
)
SELECT
  userid,
  cat1_mean,
  cat2_mean,
  cat3_mean,
  cat4_mean,
  N
FROM marked
PIVOT (
  AVG(choice) FOR QuestionGroup IN (
    cat1_mean,
    cat2_mean,
    cat3_mean,
    cat4_mean
  )
) p
;

どちらの方法も、SQL Fiddle でテストして試すことができます。

于 2012-08-24T12:01:46.220 に答える
1

それを達成するためのやや大雑把な方法ですが、

COUNT(d.userID)

COUNT(distinct d.qid)

各ユーザーに 8 のカウントを与えます。

于 2012-08-22T15:30:02.400 に答える
0
select userid, count(userid) cnt from tblTmpDemographics group by userid

これは 8 を示しています - 挿入を 2 回実行したに違いありません。

于 2012-08-22T15:29:18.683 に答える