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

问题描述 投票:2回答:2

我有一个关于在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
mysql sql group-by
2个回答
2
投票

这项工作正在进行中 - 它可能足以向您展示如何完成问题,但它还没有完成。

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

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
;
© www.soinside.com 2019 - 2024. All rights reserved.