Запрос на внутреннее объединение, где исключается несколько записей, если существует NULL - PullRequest
0 голосов
/ 26 марта 2019

У меня есть приложение, в котором пользователи отвечают на 10 вопросов, а затем получают окончательную оценку на основе ответов.Пользователи находятся в одной таблице, а ответы - в другой - они связаны с ПК пользователя (ИД пользователя).Когда пользователь запускает тест, для него создается 10 (пустых) строк, а значение answer устанавливается равным нулю.

Мне нужен способ создать запрос, чтобы рассчитать средний балл для всех пользователей, на которые были даны ответы на все 10 вопросов (т. Е. НЕ ПУСТО), и сгруппировать их по среднему.

Таблица пользователей:


| 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 ответами на вопросы (и отфильтруйте все 10 ответов для пользователей с одним или несколькими ответами как NULL).
  2. Группировать их по городам
  3. Рассчитать новое среднее по городам

Возможно ли это сделать в одном запросе?

1 Ответ

0 голосов
/ 26 марта 2019

Я думаю, вам нужно несколько уровней агрегации, сначала по пользователю, а затем по местоположению. Я думаю:

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;

Однако я думаю, что предпочитаю первую версию, потому что она не требует, чтобы все пользователи имели все десять строк в таблице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...