MySQL:多个UNION中的相同字段值

时间:2012-09-17 09:54:45

标签: mysql sql database union

我使用MySQL5.1并且我有一个表格,用于记录有关作业的操作。这是它的模式定义:

CREATE TABLE `actions_log` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `action` varchar(45) DEFAULT NOT NULL,
  `job_id` int(10) unsigned NOT NULL,
  `candidate_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

我需要创建一个请求构建器,以便用户可以使用“AND”和“OR”运算符以及括号搜索表。 SQL请求应返回候选ID。 例如,他们应该能够进行以下搜索:“ActionA OR(ActionB AND ActionC)”。

我使用UNION子句来实现这一点,并且在提供特定作业时完成工作:

SELECT `candidate_id` FROM (
    SELECT `candidate_id` FROM `actions_log` WHERE `job_id` = 1858 AND `action` = 'a'  
    UNION DISTINCT                                                                            
    (                                                                                         
        SELECT `candidate_id` FROM (
            SELECT `candidate_id`, COUNT(`candidate_id`) AS `count` FROM (
                SELECT DISTINCT `candidate_id` FROM `actions_log` WHERE `job_id` = 1858 AND `action` = 'b'
                UNION ALL                                                                                        
                SELECT DISTINCT `candidate_id` FROM `actions_log` WHERE `job_id` = 1858 AND `action` = 'c'
            ) AS level1
            GROUP BY `candidate_id`
        ) AS level2
        WHERE `count` = 2                                                                                                                              
    )                                                                                                           
) AS candidates;

用户还可以在不指定作业的情况下进行搜索。在这种情况下,任何工作都应该匹配。

这就是问题所在:行动必须是同一个工作才能成为有效的结果。 例如,使用上面的示例,作业1的“ActionA”和作业2的“(ActionB AND ActionC)”不应该是有效的匹配。

如果未指定作业,我找不到使其工作的方法。在这种情况下,UNION条款可能不是那样的。

1 个答案:

答案 0 :(得分:0)

我认为这已经足够了:

SELECT candidate_id 
FROM actions_log AS a
WHERE job_id = 1858 
  AND ( action = 'a'  
     OR action = 'b' 
    AND EXISTS 
        ( SELECT candidate_id 
          FROM actions_log 
          WHERE job_id = a.job_id
            AND action = 'c'
        )
      ) ;

或者如果您希望将条件分开,那么您可以更轻松地构建更复杂的查询:

    SELECT candidate_id 
    FROM actions_log AS a
    WHERE job_id = 1858 
      AND action = 'a'  
UNION DISTINCT
    SELECT b.candidate_id 
    FROM actions_log AS b
      JOIN actions_log AS c
        ON  c.candidate_id = b.candidate_id
        AND c.job_id = b.job_id
    WHERE b.job_id = 1858 
      AND b.action = 'b'
      AND c.action = 'c' ;