从两个表中获取min(优先级)行

时间:2016-12-22 12:33:40

标签: mysql join aggregate-functions

我需要查询来自多个表的数据,下面是主要表格(简化)。

Project
+-----+-------+-------+
| pid | pname | status|      //status: 0 = pending, 1 = complete
+-----+-------+-------+
|  1  | Proj1 |   0   |
|  2  | Proj2 |   1   |
|  3  | Proj3 |   0   |
+-----+-------+-------+

Module
+-----+--------+-------+----------+-----------------+
| mid |   pid  | status| priority |modulecategoryid |
+-----+--------+-------+----------+-----------------+    
|  1  |    1   |   1   |    1     |      1          |  
|  2  |    1   |   0   |    2     |      3          |
|  3  |    3   |   1   |    1     |      1          |
|  4  |    3   |   0   |    2     |      3          |
|  5  |    3   |   0   |    3     |      5          |
+-----+--------+-------+----------+-----------------+

Task
+----+--------+-------+----------+-----------------+
| id |   mid  | status| priority | taskcategoryid  |
+----+--------+-------+----------+-----------------+
| 1  |    2   |   1   |    2     |      2          |
| 2  |    2   |   0   |    1     |      1          |
| 3  |    4   |   1   |    1     |      2          |
| 4  |    4   |   1   |    2     |      3          |
| 5  |    4   |   0   |    3     |      4          |
| 6  |    5   |   0   |    1     |      1          |
+----+--------+-------+----------+-----------------+

我正在尝试根据模块优先级和任务优先级获取可以首先启动的所有待处理项目的待处理任务。即对于Proj3,优先级为1的模块已完成,因此我应该获得模块2的第一优先级待处理任务。

我需要使用modulecategoryid和taskcategoryid获取每个待处理项目的最先前任务,以获取此类相关信息

+-----+--------+-----+------------------+----------------+
| pid |   mid  | tid | modulecategoryid | taskcategoryid |
+-----+--------+-----+------------------+----------------+
|  1  |    2   |  2  |         3        |      2         | 
|  2  |    4   |  5  |         3        |      4         | 
+----+---------+-----+------------------+----------------+

我是MySql的新手,我尝试使用多个连接进行查询,并通过projectids和min(优先级)对其进行分组以获得所需的结果。但是,不在分组中的列是从聚合中随机获取的。

我已经看到了这个答案SQL Select only rows with Max Value on a Column,但这解决了只有一个表中数据的问题。

我能得到一些帮助吗? 如果需要,我可以发布我的查询,但是收到了错误的数据。

1 个答案:

答案 0 :(得分:1)

SQL Select only rows with Max Value on a Column有正确的方法。你只需要做两次。

首先创建一个子查询a,显示每个模块的最高优先级任务。

然后创建一个子查询b,显示每个项目的最高优先级模块。

然后将三个表和两个子查询连接在一起。

此处a。它显示每个模块id的优先级最高的任务mid。 (http://sqlfiddle.com/#!9/7eb1f3/4/0

SELECT Task.id, Task.mid
  FROM Task
  JOIN (
        SELECT MAX(priority) priority,
               mid
          FROM Task
         WHERE status = 0
             GROUP BY mid
        ) q ON q.priority = Task.priority AND q.mid = Task.mid

此处b。它的工作方式与a相同,并为每个项目mid显示优先级最高的模块pid。 (http://sqlfiddle.com/#!9/7eb1f3/3/0

SELECT Module.mid, Module.pid
  FROM Module
  JOIN (
        SELECT MAX(priority) priority,
               pid
          FROM Module
         WHERE status = 0
             GROUP BY pid
        ) q ON q.priority = Module.priority AND q.pid = Module.pid

然后你需要一个大的JOIN将所有东西拉到一起。在概述中它看起来像这样。

SELECT Project.pid, Project.pname, 
       Module.mid, Task.id tid,
       Module.modulecategoryid, Task.taskcategoryid
  FROM Project
  JOIN (  /* the subquery called b */ 
       ) b ON Project.pid = b.pid 
  JOIN Module ON b.mid = Module.mid
  JOIN (  /* the subquery called a */
       ) a ON Module.mid = a.mid
  JOIN Task ON a.id = Task.id       
 WHERE Task.status = 0

实际查询如下所示,子查询放入。(http://sqlfiddle.com/#!9/7eb1f3/2/0

SELECT Project.pid, Project.pname, 
       Module.mid, Task.id tid,
       Module.modulecategoryid, Task.taskcategoryid
  FROM Project
  JOIN (   
          SELECT Module.mid, Module.pid
            FROM Module
            JOIN (
                  SELECT MAX(priority) priority, pid
                    FROM Module
                   WHERE status = 0
                   GROUP BY pid
                 ) q   ON q.priority = Module.priority
                      AND q.pid = Module.pid
       ) b ON Project.pid = b.pid 
  JOIN Module ON b.mid = Module.mid
  JOIN ( 
          SELECT Task.id, Task.mid
            FROM Task
            JOIN (
               SELECT MAX(priority) priority, mid
                      FROM Task
                      WHERE status = 0
                      GROUP BY mid
                 ) q    ON q.priority = Task.priority
                       AND q.mid = Task.mid
       ) a ON Module.mid = a.mid
  JOIN Task ON a.id = Task.id       
 WHERE Task.status = 0

这样做的秘诀是理解子查询是虚拟表,您可以将它们相互连接或连接到普通表。您需要的技能是整理所需的物理和虚拟表以及连接顺序。