如何在MySQL 5.7中组织此查询?

时间:2019-04-25 21:41:54

标签: mysql sql group-by

我对在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', 'jdoe@demo.net', UNIX_TIMESTAMP());
INSERT INTO m_user (username, firstname, lastname, email, timecreated) VALUES('user2', 'Jane', 'Doe', 'janedoe@demo.net', 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

2 个答案:

答案 0 :(得分:2)

这项工作仍在进行中-可能足以向您展示如何完成问题,但还远远不够。

@Query("SELECT _key, secondName FROM Person WHERE firstName REGEXP ?")
public List<List> selectSeveralField(String val, Pageable pageable);

答案 1 :(得分:0)

由于内维尔·库伊特(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
;