【问题标题】:Inner join query where excluding multiple entries if NULL exists如果存在NULL,则排除多个条目的内部联接查询
【发布时间】:2019-08-16 17:49:19
【问题描述】:

我有一个应用程序,用户在其中回答 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;

我想:

  1. 计算每个用户回答 10 个问题的平均分数(并过滤掉所有回答一个或多个为 NULL 的用户的所有 10 个答案)。
  2. 按城市分组
  3. 按城市计算新平均值

这甚至可以在一个查询中完成吗?

【问题讨论】:

  • 也向我们展示预期的结果! (有上表数据。)
  • “回答了 10 个问题”,您的意思是至少 10 个,还是正好 10 个?
  • 我的意思是 10 个,因为测验中只有 10 个答案。因此,如果用户已经回答了所有问题,则查询应该显示它 - 否则不会

标签: sql postgresql inner-join


【解决方案1】:

我认为您需要多个级别的聚合,首先按用户,然后按位置。我认为:

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;

但是,我认为我更喜欢第一个版本,因为它不需要所有用户在表中都有所有十行。

【讨论】:

    猜你喜欢
    • 2020-09-08
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多