SQLite Соединение нескольких таблиц упорядочение по меньшему количеству COUNT - PullRequest
0 голосов
/ 02 июля 2018

У меня есть такая структура базы данных:

enter image description here

Мне нужно отобразить users, который может выполнить Task определенного типа в один конкретный день, показывая сначала результаты, для которых Tasks (или вообще нет Task) назначено меньше в тот день.

Например:

  • User A имеет 1 Task типа 1, назначенного на этот день.
  • User B имеет 3 Task типа 1, назначенного на этот день.
  • User C не имеет Task типа 1, назначенного в этот день.

Я хочу отобразить их в следующем порядке: Пользователь C> Пользователь A> Пользователь B

Вот мой запрос:

SELECT  *, COUNT(*)
FROM USER U
INNER JOIN USER_TASK_TYPE UT ON (U._id=UT.user_id)
LEFT JOIN TASK T ON (U._id = T.user_id)
where UT.TASK_TYPE_ID = ?
where T.CREATION_DATE = ?
GROUP BY T.user_id
ORDER BY COUNT(*) ASC;

Что-то все еще не так, потому что если одному User назначено 1 задание, а другому User не выполнено ни одного, все равно первый User отображается первым.

Буду признателен за любую помощь. Спасибо.

1 Ответ

0 голосов
/ 02 июля 2018

Сначала указанная схема не отражает используемый запрос: -

  • В таблице task нет столбца creation_date .
  • Столбец id для таблицы user должен иметь значение _id .

Во-вторых, указанный вами запрос приведет к синтаксической ошибке из-за того, что WHERE кодируется дважды.

Ваше описание существующих данных неясно, например, Вы говорите: -

Пользователь А имеет 1 задание типа 1, назначенное на этот день

Какая строка (и) существует в какой таблице?

В качестве предположения было использовано следующее

  • отмечая, что: -
    • Существует несколько пользователей, для которых не существует задач
    • и существует пользователь, для которого в этот день не существует ни одной задачи

: -

-- DROP and Recreate/Create tables
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS task;
DROP TABLE IF EXISTS task_type;
DROP TABLE IF EXISTS user_task_type;
CREATE TABLE IF NOT EXISTS user (_id INTEGER PRIMARY KEY,  name TEXT, user_id INTEGER, user_name TEXT, password TEXT, user_type TEXT);
CREATE TABLE IF NOT EXISTS task(id INTEGER PRIMARY KEY, creation_date TEXT, description TEXT, duration int, status TEXT, user_id INTEGER, task_type_id INTEGER);
CREATE TABLE IF NOT EXISTS task_type(id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE IF NOT EXISTS user_task_type (id INTEGER PRIMARY KEY, user_id INTEGER, task_type_id INTEGER);

-- Add some users
INSERT INTO user (name,password,user_type) VALUES
    ('USER1','x','x'),('USER2','x','x'),('USER3','x','x'),('USER4','x','x'),('USER5','x','x'); 

-- Add some task types
INSERT INTO task_type (name) VALUES
    ('Sweep'),('Wash'),('Polish'),('Scrub');

-- Add some tasks for users
INSERT INTO task (creation_date, description, duration, status, user_id, task_type_id) VALUES
    ('2018-01-01','USER1 TASK01',10,'to be done', 1,1),
    ('2018-01-01','USER2 TASK01',10,'to be done', 2,1),
    ('2018-01-01','USER2 TASK01',10,'to be done', 2,1),
    ('2018-01-01','USER2 TASK01',10,'to be done', 2,1),
    ('2018-02-02', 'USER3 NOT ON THE DAY',10,'to be done another day',3,1) --<<<< for testing user on another day
    -- ('2018-01-01','???????',10,'????????',3,1); commented out used for testing
    ;

-- unclear what this is used for but match tasks SUPERFLUOUS?
INSERT INTO user_task_type (user_id, task_type_id) VALUES
    (1,1),(2,1),(2,1),(2,1),(3,1),
    (3,1) -- added a spurious row;
    ;

SELECT  *, COUNT(*)
FROM USER U
    JOIN USER_TASK_TYPE UT ON (U._id=UT.user_id)
    JOIN TASK T ON (U._id = T.user_id)
WHERE UT.TASK_TYPE_ID = 1
-- WHERE T.CREATION_DATE = '2018-01-01' <<<<<<<<<< Invalid used the following line
AND T.CREATION_DATE = '2018-01-01' -- <<<<<<<<<< assumed AND
GROUP BY T.user_id
ORDER BY COUNT(*) ASC;

В результате получается то, что кажется ожидаемым (нет ложных строк для пользователей, у которых нет задач или у которых нет задач в день). Тем не менее, счет не такой, как ожидалось, а в квадрате. : -

enter image description here

Я полагаю, что проблема с подсчетом связана с использованием таблицы user_task_type, которая представляется избыточной и проблемной. Таким образом, следующее может быть в соответствии с тем, что вы хотите: -

SELECT  *, COUNT(*)
FROM USER U
    -- INNER JOIN USER_TASK_TYPE UT ON (U._id=UT.user_id)
    JOIN TASK T ON (U._id = T.user_id)
    JOIN task_type tt ON tt.id = t.task_type_id
WHERE  tt.id = 1 AND T.CREATION_DATE = '2018-01-01'
GROUP BY T.user_id
ORDER BY COUNT(*) ASC;

В результате: -

enter image description here

  • т.е. Таблица user_task_type не была объединена, так как кажется, что она не имеет смысла, а количество соответствует ожидаемому
...