[英]Postgres calculate average using distinct IDs‚ values also distinct
我有一個 postgres 查詢,它應該根據一組值計算平均值。 這組值應基於 DISTINCT ID。
查詢如下:
#{context.answers_base}
SELECT
stores.name as store_name,
answers_base.question_name as question_name,
answers_base.question_id as question_id,
(sum(answers_base.answer_value) / NULLIF(count(answers_base.answer_id),0)) as score, # <--- this line is calculating wrong
sum(answers_base.answer_value) as score_sum,
count(answers_base.answer_id) as question_answer_count,
count(DISTINCT answers_base.answer_id) as answer_count
FROM answers_base
INNER JOIN stores ON stores.id = answers_base.store_id
WHERE answers_base.answer_value IS NOT NULL AND answers_base.question_type_id = :question_type_id
AND answers_base.scale = TRUE
#{context.filter_answers}
GROUP BY stores.name, answers_base.question_name, answers_base.question_id, answers_base.sort_order
ORDER BY stores.name, answers_base.sort_order
問題是,在指示的行(sum(answers_base.answer_value) / NULLIF(count(answers_base.answer_id),0))
中,某些值被多次計算。
部分解決方案是根據 ID 使其成為 DISTINCT,如下所示: (sum(answers_base.answer_value) / NULLIF(count(DISTINCT answers_base.answer_id),0))
這將導致除以正確數字的平均值,但這里它除以的總和仍然是錯誤的。
執行以下操作 (make sum() DISTINCT) 不起作用,因為值不是唯一的。 這些值是 0 / 25 / 50 / 75 / 100,因此不同的 ID 可能包含“相同”的值。 (sum(DISTINCT answers_base.answer_value) / NULLIF(count(DISTINCT answers_base.answer_id),0))
我將如何 go 使這項工作?
以下是表結構的簡化版本。
表格答案
ID | 回答日期 |
---|---|
1個 | 2022 年 2 月 1 日 |
2個 | 2022 年 3 月 2 日 |
3個 | 2022 年 3 月 13 日 |
4個 | 2022 年 3 月 21 日 |
表AnswerRow
ID | answer_id | 答案值 |
---|---|---|
1個 | 1個 | 25 |
2個 | 1個 | 50 |
3個 | 1個 | 50 |
4個 | 2個 | 75 |
5個 | 2個 | 100 |
6個 | 2個 | 0 |
7 | 3個 | 25 |
8個 | 4個 | 25 |
9 | 4個 | 100 |
10 | 4個 | 50 |
答案 1' answer_rows
: 25 + 50 + 50 -> average = 125 / 3
答案 2' answer_rows
: 75 + 100 + 0 -> average = 175 / 3
答案 3' answer_rows
: 25 -> average = 25 / 1
答案 4' answer_rows
:25 + 100 + 50 -> average = 175 / 3
由於某種原因,我們在計算中得到了重復的 answer_rows。
問題的例子; 對於answer_id=1
我們在計算中有以下 answer_rows,給我們一個不同的平均值:
ID | answer_id | 答案值 |
---|---|---|
1個 | 1個 | 25 |
2個 | 1個 | 50 |
3個 | 1個 | 50 |
3個 | 1個 | 50 |
3個 | 1個 | 50 |
3個 | 1個 | 50 |
結果: 25 + 50 + 50 + 50 + 50 + 50 -> 275 / 6
期望結果: 25 + 50 + 50 -> 125 / 3
使 answer_row_id 不同(見帖子開頭)使我有可能得到: 25 + 50 + 50 + **50 + 50 + 50** -> 275 / **3**
但不是25 + 50 + 50 -> 275 / 3
我想要實現的是根據其 ID 明確選擇answer_row
的計算,並且這些answer_rows 將在計算average -> x / y
中用於計算x
和y
。
answers_base 如下(簡化):
WITH answers_base as (
SELECT
answers.id as answer_id,
answers.store_id as store_id,
answer_rows.id as answer_row_id,
question_options.answer_value as answer_value
FROM answers
INNER JOIN answer_rows ON answers.id = answer_rows.answer_id
INNER JOIN stores ON stores.id = answers.store_id
WHERE answers.status = 0
)
我認為這最好用window function解決。 類似的東西
SELECT
ROW_NUMBER() OVER (PARTITION BY answer_rows.id ORDER BY answer_rows.created_at DESC) AS duplicate_answers
...
WHERE
answer_rows.duplicate_answers = 1
這將過濾掉具有相同id
的多行,並且只保留一個條目。 (我選擇了“first by created_at
”,但您可以將其更改為最適合您的邏輯。)
這種方法的一個好處是它使邏輯背后的基本原理清晰、包含和可重用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.