我有一个应用程序,用户可以在其中回答10个问题,然后根据答案获得最终分数。用户在一个表中,而答案在另一个表中-这些通过用户的PK(用户ID)链接在一起。当用户开始测试时,将为该用户创建10(空)行,并且answer
值将设置为null。
我需要一种创建查询的方式来计算所有已回答了全部10个问题(即NOT NULL)的所有用户的平均得分,并将它们按平均值分组。
| userid | location | name |
|--------|------------|-------------|
| 1 | New York | John |
| 2 | Chicago | Mike |
| 3 | New York | Daisy |
| 4 | Los Angeles| Jane |
| 5 | Chicago | Bob |
| aId | userid | answer |question|
|-----|--------|--------|--------|
| 001 | 1 | 8 | 1 |
| 002 | 1 | 7 | 2 |
| 003 | 1 | 5 | 3 |
| 004 | 1 | 3 | 4 |
| 005 | 1 | 10 | 5 |
| 006 | 1 | 3 | 6 |
| 007 | 1 | 6 | 7 |
| 008 | 1 | 4 | 8 |
| 009 | 1 | 2 | 9 |
| 010 | 1 | 8 | 10 |
| 011 | 2 | 8 | 1 |
| 012 | 2 | 7 | 2 |
| 013 | 2 | 5 | 3 |
| 014 | 2 | 3 | 4 |
| 015 | 2 | NULL | 5 |
| 016 | 2 | NULL | 6 |
| 017 | 2 | NULL | 7 |
| 018 | 2 | NULL | 8 |
| 019 | 2 | NULL | 9 |
| 020 | 2 | NULL | 10 |
....
在上面的示例中,一个用户有10个回答的问题,而一个用户只有4个回答的问题。目标是从查询中排除User #2
,而仅选择User #1
(以及其他获得完整结果的用户)
到目前为止,这是我的发言,但不排除具有空值的用户的答案。我需要的是某种if语句来检查类似(IF a.answer IS NULL
“不要使用此用户的答案”)
SELECT AVG(a.answer), u.clocation FROM answers a
INNER JOIN users u
ON u.userid = a.userid
GROUP BY u.clocation;
这甚至可以在一个查询中完成吗?
答案 0 :(得分:0)
我认为您需要多个聚合级别,首先是按用户,然后是位置。我认为:
SELECT u.clocation, AVG(avg_answer)
FROM (SELECT a.userid, AVG(a.answer) as avg_answer
FROM answers a
WHERE a.answer IS NOT NULL
GROUP BY a.userid
HAVING COUNT(*) = 10
) a JOIN
users u
ON u.userid = a.userid
GROUP BY u.clocation;
如果所有用户都有十行-即使对于未回答的问题,那么您也可以这样做:
SELECT u.clocation, AVG(a.answer)
FROM answers a JOIN
users u
ON u.userid = a.userid
WHERE NOT EXISTS (SELECT 1
FROM answers a2
WHERE a2.userid = a.userid AND
a2.answer IS NOT NULL
)
GROUP BY u.clocation;
但是,我认为我更喜欢第一个版本,因为它不需要所有用户在表中拥有所有十行。