2

ごとの方法ではなく、ごとの方法でいくつかの値を平均化する必要があります。(列ごとの平均を行っている場合は、 を使用できます)。これの私の特定のアプリケーションでは、平均化で NULL を無視する必要があります。これは非常に単純なロジックですが、SQL で行うのは非常に難しいようです。私の計算を行うエレガントな方法はありますか?avg()

価値があるので、私はSQLite3を使用しています。

詳細

詳細が必要な場合は、次の図をご覧ください。

私は調査のあるテーブルを持っています:

| q1 | q2    | q3    | ... | q144 |
|----|-------|-------|-----|------|
| 1  | 3     | 7     | ... | 2    |
| 4  | 2     | NULL  | ... | 1    |
| 5  | NULL  | 2     | ... | 3    |

(これらは値の例と単純な列名です。有効な値は 1 ~ 7 および NULL です。)

次のようにいくつかの平均を計算する必要があります。

q7 + q33 + q38 + q40 + ... + q119 / 11 as domain_score_1
q10 + q11 + q34 + q35 + ... + q140 / 13 as domain_score_2
...
q2 + q5 + q13 + q25 + ... + q122 / 12 as domain_score_14

...しかし、非ヌルに基づいてヌルと平均を引き出す必要があります。したがって、domain_score_1(11個のアイテムがある)の場合、次のことを行う必要があります。

Input:  3, 5, NULL, 7, 2, NULL, 3, 1, 5, NULL, 1

(3 + 5 + 7 + 2 + 3 + 1 + 5 + 1) / (11 - 3)
27 / 8
3.375

私が検討している単純なアルゴリズムは次のとおりです。

入力:

3, 5, NULL, 7, 2, NULL, 3, 1, 5, NULL, 1 

NULL の場合、各値を 0 に結合します。

3, 5, 0, 7, 2, 0, 3, 1, 5, 0, 1

和:

27

値 > 0 を 1 に変換して合計することにより、非ゼロの数を取得します。

3, 5, 0, 7, 2, 0, 3, 1, 5, 0, 1
1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1
8

その 2 つの数を割ります

27 / 8
3.375

しかし、それはこれが必要とするよりもはるかに多くのプログラミングのようです. 私が気付いていないエレガントな方法はありますか?

アップデート:

私が何かを誤解していない限りavg()、これではうまくいきません。私がやりたいことの例:

select avg(q7, q33, q38, ..., q119) from survey;

出力:

SQL error near line 3: wrong number of arguments to function avg()
4

5 に答える 5

4

標準SQLでは

SELECT 
(SUM(q7)+SUM(q33)+SUM(q38)+SUM(q40)+..+SUM(q119))/
(COUNT(q7)+COUNT(q33)+COUNT(q38)+COUNT(q40)+..+COUNT(q119)) AS domain_score1 
FROM survey

NULL の場合、SUM は合体して 0 になり、COUNT は NULL をカウントしません。(SQLite3が準拠することを願っています)。

編集: http://www.sqlite.org/lang_aggfunc.htmlと SQLite の準拠を確認しました。sum() がオーバーフローする場合は、代わりに total() を使用できます。

また、正規化に関する意見を支持します。テーブルのデザインを正規化しないと (そして、名前に数字が含まれる列が表示されるたびに赤い旗が表示されます)、洗練された SQL は作成されません。

于 2010-03-30T16:06:01.077 に答える
4

AVGすでにヌルを無視して、あなたが望むことをします:

avg() 関数は、グループ内のすべての非 NULL X の平均値を返します。数値のように見えない文字列および BLOB 値は、0 として解釈されます。 avg() の結果は、すべての入力が整数であっても、NULL 以外の入力が少なくとも 1 つある限り、常に浮動小数点値です。avg() の結果は、NULL 以外の入力がない場合にのみ NULL になります。

http://www.sqlite.org/lang_aggfunc.htmlから

したがって、ドメインごとに持っている値を取得して別のテーブルにロードし、そのテーブルで平均を実行することができます。または、ワイド テーブルのピボットを解除して、その上で平均を実行することもできます。


AVG行ではなく列で機能します。したがって、テーブルのピボットを解除した場合は、使用できAVG、直面している問題は発生しません。小さな例を見てみましょう:

テーブルがあり、次のようになります。

ID  | q1  | q2  | q3
----------------------
1   | 1   | 2   | NULL
2   | NULL| 2   | 56

q1 と q2 は同じドメインにあるため一緒に平均化したいのですが、それらは別々の列であるためできません。ただし、テーブルを次のように変更した場合:

ID  | question | value
-----------------------
1   | 1        | 1
1   | 2        | 2
1   | 3        | NULL
2   | 1        | NULL
2   | 2        | 2
2   | 3        | 56

次に、2 つの質問の平均を簡単に取ることができます。

SELECT AVG(value)
FROM Table
WHERE question IN (1,2)

また、グローバル平均ではなく ID ごとの平均が必要な場合は、ID でグループ化できます。

SELECT ID, AVG(value)
FROM Table
WHERE question IN (1,2)
GROUP BY ID
于 2010-03-30T15:37:39.087 に答える
2

これは巨大なクエリになりますが、これを行うことができます:

SELECT AVG(q) FROM
((SELECT q7 AS q FROM survey) UNION ALL
(SELECT q33 FROM survey) UNION ALL
(SELECT q38 FROM survey) UNION ALL
...
(SELECT q119 FROM survey))

これにより、列が行に変換され、AVG()関数が使用されます。

もちろん、これは特定の調査レコードに対してのみ必要になる可能性があるため、WHERE句を忘れないでください。

SELECT AVG(q) FROM
((SELECT q7 AS q FROM survey WHERE survey_id = 1) UNION ALL
(SELECT q33 FROM survey WHERE survey_id = 1) UNION ALL
(SELECT q38 FROM survey WHERE survey_id = 1) UNION ALL
...
(SELECT q119 FROM survey WHERE survey_id = 1))

行ごとに1つの質問を使用して、q列を独自のテーブルに正規化し、調査に戻って参照すると、はるかに簡単な時間になります。調査と質問の間には1対多の関係があります。

于 2010-03-30T15:53:09.973 に答える
1

別のテーブルを使用して、さまざまな質問の調査スコアを保存します (q は質問によるものと仮定します)。以下のようなもの

SurveyTable(SurveyId, ...)
SurveyRatings(SurveyId, QuestionId, Rating)

その後、次のようなクエリを実行できます

SELECT avg(Rating) WHERE SurveyId=?
于 2010-03-30T15:50:08.280 に答える
0

使用する:

SELECT AVG(x.answer)
  FROM (SELECT s.q7 AS answer
          FROM SURVEY s
        UNION ALL
        SELECT s.q33
          FROM SURVEY s
        UNION ALL    
       SELECT s.q38
         FROM SURVEY s
       ...
       UNION ALL
       SELECT s.q119
         FROM SURVEY s) x

使用しないでくださいUNION- 存在する場合は重複が必要です。

于 2010-03-30T16:19:24.897 に答える