我有一个关于在MySQL 5.7中形成查询的方法的问题。
首先,这里是表结构和示例数据:
create table m_user
(
id bigint(10) auto_increment primary key,
deleted tinyint(1) default 0 not null,
suspended tinyint(1) default 0 not null,
username varchar(100) default '' not null,
password varchar(255) default '' not null,
idnumber varchar(255) default '' not null,
firstname varchar(100) default '' not null,
lastname varchar(100) default '' not null,
email varchar(100) default '' not null,
timecreated bigint(10) default 0 not null,
timemodified bigint(10) default 0 not null
);
INSERT INTO m_user (username, firstname, lastname, email, timecreated) VALUES('user1', 'John', 'Doe', '[email protected]', UNIX_TIMESTAMP());
INSERT INTO m_user (username, firstname, lastname, email, timecreated) VALUES('user2', 'Jane', 'Doe', '[email protected]', UNIX_TIMESTAMP());
create table m_workflow
(
id bigint(10) auto_increment primary key,
name varchar(255) default '' not null,
timecreated bigint(10) default 0 not null,
timemodified bigint(10) default 0 not null
);
INSERT INTO m_workflow (name, timecreated) VALUES('nr1', UNIX_TIMESTAMP());
INSERT INTO m_workflow (name, timecreated) VALUES('nr2', UNIX_TIMESTAMP());
create table m_workflow_questions
(
id bigint(10) auto_increment primary key,
workflowid bigint(10) not null,
title varchar(255) default '' not null,
timecreated bigint(10) default 0 not null,
timemodified bigint(10) default 0 not null
);
INSERT INTO m_workflow_questions (workflowid, title, timecreated) VALUES(1, 'Q1', UNIX_TIMESTAMP());
INSERT INTO m_workflow_questions (workflowid, title, timecreated) VALUES(1, 'Q2', UNIX_TIMESTAMP());
INSERT INTO m_workflow_questions (workflowid, title, timecreated) VALUES(1, 'Q3', UNIX_TIMESTAMP());
create table m_workflow_answers
(
id bigint(10) auto_increment primary key,
workflowid bigint(10) default 0 not null,
questionid bigint(10) default 0 not null,
answer longtext not null,
value bigint(10) default 0 not null,
timecreated bigint(10) default 0 not null,
timemodified bigint(10) default 0 not null
);
INSERT INTO m_workflow_answers (workflowid, questionid, answer, timecreated) VALUES(1, 1, 'a1', UNIX_TIMESTAMP());
INSERT INTO m_workflow_answers (workflowid, questionid, answer, timecreated) VALUES(1, 1, 'b1', UNIX_TIMESTAMP());
INSERT INTO m_workflow_answers (workflowid, questionid, answer, timecreated) VALUES(1, 1, 'c1', UNIX_TIMESTAMP());
INSERT INTO m_workflow_answers (workflowid, questionid, answer, timecreated) VALUES(1, 2, 'd1', UNIX_TIMESTAMP());
INSERT INTO m_workflow_answers (workflowid, questionid, answer, timecreated) VALUES(1, 2, 'f1', UNIX_TIMESTAMP());
INSERT INTO m_workflow_answers (workflowid, questionid, answer, timecreated) VALUES(1, 3, 'k1', UNIX_TIMESTAMP());
INSERT INTO m_workflow_answers (workflowid, questionid, answer, timecreated) VALUES(1, 3, 'j1', UNIX_TIMESTAMP());
create table m_workflow_responses
(
id bigint(10) auto_increment primary key,
questionid bigint(10) default 0 not null,
userid bigint(10) default 0 not null,
answerid bigint(10) default 0 not null,
timecreated bigint(10) default 0 not null,
timemodified bigint(10) default 0 not null
);
INSERT INTO m_workflow_responses (questionid, userid, answerid, timecreated) VALUES(1, 1, 1, UNIX_TIMESTAMP());
INSERT INTO m_workflow_responses (questionid, userid, answerid, timecreated) VALUES(2, 1, 2, UNIX_TIMESTAMP());
INSERT INTO m_workflow_responses (questionid, userid, answerid, timecreated) VALUES(1, 2, 2, UNIX_TIMESTAMP());
INSERT INTO m_workflow_responses (questionid, userid, answerid, timecreated) VALUES(2, 2, 3, UNIX_TIMESTAMP());
我们在这里创建了几个表 - m_user,m_workflow,m_workflow_questions,m_workflow_answers,m_workflow_responses
有一个工作流程可以有一个或多个问题。每个问题可以包含至少2个或更多定义的答案。用户可以通过为每个问题选择一个或多个提供的答案来回答问题。这是一种多种选择的测试方式。这些用户选择中的每一个都存储在m_workflow_responses表中。
我现在需要做的是提供一个简单的所有用户列表,以及他们在特定工作流程中的状态。
例:
User Workflow Status Started Finished
John Doe Started 12/12/18 --
Jane Doe Not started -- --
Jimmy Doe Completed 11/12/18 12/12/18
我遇到的问题与确定特定问题是否被视为已完成的方式有关。
我的想法是计算问题的数量和用户对问题的不同回答的数量并进行比较。
这就是我所拥有的,但它是不正确的。它未提供工作流程中可用问题的正确计数
SELECT mq.workflowid
, COUNT(mq.id) AS mqcount
, mr.userid
, SUM(CASE WHEN mr.userid IS NOT NULL THEN 1 END) AS mrcount
FROM m_workflow_questions mq
LEFT JOIN (
SELECT mra.questionid, mra.userid
FROM m_workflow_responses mra
GROUP BY mra.questionid, mra.userid
) mr ON mr.questionid = mq.id
GROUP BY mq.workflowid, mr.userid
这是具有相同表结构和测试数据的SQL小提琴:
http://sqlfiddle.com/#!9/1d6db3/2
注意:SQL小提琴使用MySQL 5.6,但我提供了确切的SQL_MODE设置来模拟行为。
进一步澄清:
我的主要问题是确定工作流程的完成情况。当用户对至少一个响应的所有问题做出响应时,完成用户的工作流程。所以我需要的是计算所回答的问题的数量而不是总的给定响应的数量,因为一个问题可以具有来自一个用户的多个响应。这是我想在工作流程中计算用户响应问题数量的方式:
SELECT COUNT(DISTINCT(mq.id)) AS mrcount
FROM m_workflow_questions mq
JOIN m_workflow_responses mr ON mr.questionid = mq.id
WHERE mr.userid = 3 AND mq.workflowid = 1
这项工作正在进行中 - 它可能足以向您展示如何完成问题,但它还没有完成。
select u.id,
u.firstname,
u.lastname,
w.name,
min(wr_start.timecreated),
max(wr_end.timecreated),
(select count(*)
from m_workflow_questions
where workflowid = w.id) as total_questions,
(select count(*)
from m_workflow_responses
where userid = u.id) as answered_questions
from m_user u
left outer join m_workflow_responses wr_start
on u.id = wr_start.userid
left outer join m_workflow_answers wa
on wr_start.questionid = wa.questionid
left outer join m_workflow w on w.id = wa.workflowid
left outer join m_workflow_responses wr_end
on u.id = wr_end.userid
group by u.id,
u.firstname,
u.lastname,
w.name,
w.id
感谢Neville Kuyt非常有用的想法,我做了以下事情:
workflowid
添加到m_workflow_responses
表中现在它看起来像这样:
SELECT t.id, t.userid, (t.mqcount = t.mrcount) AS complete , t.started, t.completed
FROM (
SELECT m.id
, mr.userid
, (SELECT COUNT(*) FROM m_workflow_questions mq1 WHERE mq1.workflowid = m.id) AS mqcount
, COUNT(DISTINCT (mr.questionid)) AS mrcount
, (SELECT MIN(mr1.timecreated) FROM m_workflow_responses mr1 WHERE mr1.userid = mr.userid AND mr1.workflowid = m.id) AS started
, (SELECT MAX(mr2.timecreated) FROM m_workflow_responses mr2 WHERE mr2.userid = mr.userid AND mr2.workflowid = m.id) AS completed
FROM m_workflow m
JOIN m_workflow_questions mq ON mq.workflowid = m.id
LEFT JOIN m_workflow_responses mr ON mr.questionid = mq.id
WHERE mr.userid IS NOT NULL
GROUP BY m.id, mr.userid
) t
;