内部联接查询,如果存在NULL,则排除多个条目

时间:2019-03-26 11:02:42

标签: sql postgresql inner-join

我有一个应用程序,用户可以在其中回答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. 按城市计算新的平均值

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

1 个答案:

答案 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;

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