如何根据MySQL中子查询结果的组合选择特定值

时间:2015-03-26 06:48:10

标签: mysql

假设下面是MyTable:

----------------------------------------
    employee_id task_id Subtask_id  name    pager   checked 
----------------------------------------
    1           124     1           Jackson 555     2015-05-10  
    1           124     2           Jackson 555     2015-06-10  
    1           124     3           Jackson 555     NULL    
    2           789     1           Nancy   333     2015-05-10  
    3           222     1           Jane    555     NULL    
    3           963     1           Jane    555     NULL    
    1           422     1           Jackson 555     2015-06-10  
----------------------------------------

我在MySQL中写了这个查询:

SELECT employee_id, task_id, Name, Pager, if(count(Q.employee_ID) > 1,"Incomplete",if(Q.BoolChecked = 0,"None", "Done") AS STATUS
FROM (
SELECT employee_ID, task_id, Name, Pager, if(Checked IS NULL,0,1) AS BoolChecked
FROM MyTable
GROUP BY task_id, BoolChecked
) AS Q
GROUP BY Q.task_id

结果如下:

----------------------------------------
    employee_id task_id name    pager   checked 
----------------------------------------
    1           124     Jackson 555     Incomplete  
    1           422     Jackson 555     Done    
    2           789     Nancy   333     Done    
    3           222     Jane    555     None
    3           963     Jane    555     None    

我无法实现并需要帮助的最终目标是按employee_id进行分组并获得以下结果:

--------------------------------
    employee_id name    pager   checked 
--------------------------------
    1           Jackson 555     Incomplete  
    2           Nancy   333     Done    
    3           Jane    555     None    

摘要:如果所有任务都已完成,则按employee_id显示“完成”。如果未完成所有任务,请显示“无”。任何组合节目都不完整“

  • 问题1:如何实现最终结果?
  • 问题2:对我已经拥有的查询的任何性能评论?

非常感谢你的帮助。

2 个答案:

答案 0 :(得分:0)

我认为你可以在没有子查询的情况下完成整个事情,只需分组和使用条件。请注意,CASE会比IF好,但我懒得查找语法:

SELECT employee_id, name, pager, 
    SUM(IF(checked IS NULL, 1, 0)) AS NullCount,
    SUM(IF(checked IS NOT NULL, 1, 0)) AS CompleteCount,
    IF(NullCount > 0 AND CompleteCount > 0, 
        'Incomplete', 
        IF(CompleteCount > 0, 'Done', 'None') AS Status
FROM MyTable
GROUP BY employee_id, name, `pager`

同样,如果用IF()替换嵌套的CASE,它会更好看。如果你把NullCount和CompleteCount作为额外的列而烦恼,那么你可以将它们放在IF中 - 它似乎只是让它更加清晰(并且不需要重复计算) CompleteCount)。

我抬起CASE - 在这里,完全未经测试:

SELECT employee_id, name, pager, 
    SUM(IF(checked IS NULL, 1, 0)) AS NullCount,
    SUM(IF(checked IS NOT NULL, 1, 0)) AS CompleteCount,
    CASE
        WHEN (SUM(IF(checked IS NULL, 1, 0)) > 0 AND SUM(IF(checked IS NOT NULL, 1, 0)) > 0) THEN 'Incomplete'
        WHEN (SUM(IF(checked IS NOT NULL, 1, 0)) > 0) THEN 'Done'
        ELSE 'None' 
    END AS Status
FROM MyTable
GROUP BY employee_id, name, `pager`

答案 1 :(得分:0)

count(*)计算所有行,而count(expression)计算expression IS NOT NULL行。你需要的实际上是expression IS NULL行的数字 - 最简单的方法就是减去两个值。试试这个:

SELECT
  `employee_id`, `name`, `pager`
  , CASE 
    WHEN (count(*) - count(`checked`)) > 0 THEN 'Incomplete'
    ELSE 'done'
   END AS checked
 FROM MyTable
 GROUP BY `employee_id`, `name`, `pager`

这里有一个小问题:http://sqlfiddle.com/#!9/df620/3

第二件事:假设'南希'只有未完成的任务 - 你为什么要让她被标记为“无”?为了能够这样说,您需要重新设计架构。将您的表分成两部分:“员工”和“任务”。然后你可以进行左连接 - 如果某个员工没有行 - 那么你可以将他标记为'无'。如果你真的想要它 - 你可以尝试下面的查询:

SELECT
  `employee_id`, `name`, `pager`
  , CASE 
    WHEN max(`checked`) IS NULL AND min(`checked`) IS NULL THEN 'none'
    WHEN (count(*) - count(`checked`)) > 0 THEN 'Incomplete'
    ELSE 'done'
   END AS checked
 FROM MyTable
 GROUP BY `employee_id`, `name`, `pager`

这是一个小提琴:http://sqlfiddle.com/#!9/df620/5