mysql替代INTERSECT

时间:2013-01-21 16:39:43

标签: mysql sql intersect

我一直在尝试删除相交,因为它不受mysql支持。如果有人能提供一些指示,那将非常有用。

SELECT *, DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age 
FROM user U, user_utilisation UU 
WHERE U.id_user = UU.id_user AND cp >= 1 AND cp <= 3000 AND sexe = 'M' AND UU.id_mailing = 6 
GROUP BY U.id_user 
HAVING age >= 1 AND age <= 100 
ORDER BY nom, prenom

INTERSECT 

SELECT *, DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age 
FROM user U, user_utilisation UU 
WHERE U.id_user = UU.id_user AND cp >= 1 AND cp <= 3000 AND sexe = 'M' AND UU.id_mailing = 7 
GROUP BY U.id_user 
HAVING age >= 1 AND age <= 100 
ORDER BY nom, prenom

我试过JOIN(s),但这就是我现在所拥有的:

SELECT *, DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(naissance, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(naissance, '00-%m-%d')) AS age 
FROM user U, user_utilisation UU 
WHERE U.id_user = UU.id_user AND cp >= 1 AND cp <= 3000 AND sexe = 'M' 
    AND UU.id_user IN (select id_user from user_utilisation where id_mailing = 6 OR id_mailing = 7) 
HAVING age >= 1 AND age <= 100 
ORDER BY nom, prenom

但是删除了GROUP BY我发现查询选择了2个记录id_mailing = 1,而GROUP BY隐藏了错误的记录。我很确定这可能会导致问题...

user_utilisation只有三个字段id_userid_mailingdate

3 个答案:

答案 0 :(得分:2)

解释您的疑问,在我看来:

  1. 您希望获得所有参与mailing_id 6和7的用户(这就是您正在使用INTERSECT的原因,是吗?)。
  2. 您希望按条件限制这些用户并执行年龄计算。
  3. 如果我对你的意图的解释是正确的(完全不确定是这种情况!),你根本不需要INTERSECT,你应该能够简单地用标准选择你想要的用户您想要,并通过JOIN限制参与邮寄6和7:

    SELECT *, DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age 
    FROM user U
    INNER JOIN user_utilisation UU on U.id_user = UU.id_user and UU.mailing_id = 6
    INNER JOIN user_utilisation UU2 on U.id_user = UU2.id_user and UU2.mailing_id = 7
    WHERE cp >= 1 AND cp <= 3000 AND sexe = 'M' 
    HAVING age >= 1 AND age <= 100 
    ORDER BY nom, prenom
    

答案 1 :(得分:1)

您可以尝试以下内容:

SELECT *
  FROM
      (SELECT *
            , DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age 
        FROM user U
             INNER JOIN user_utilisation UU 
                     ON U.id_user = UU.id_user
        WHERE cp >= 1 AND cp <= 3000 
              AND sexe = 'M'
              AND UU.id_mailing = 6 
        GROUP BY U.id_user 
        HAVING age >= 1 AND age <= 100) QUERY1
 WHERE EXISTS(SELECT *
            , DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age 
        FROM user U
             INNER JOIN user_utilisation UU 
                     ON U.id_user = UU.id_user
        WHERE cp >= 1 AND cp <= 3000 
              AND sexe = 'M'
              AND UU.id_mailing = 7
              AND U.id_user = QUERY1.id_user
        GROUP BY U.id_user 
        )
ORDER BY nom, prenom

上面查询中的技巧是WHERE EXISTS(...)子句充当过滤器,类似于之前使用的INTERSECT。我们的想法是,您只想从查询QUERY1中选择满足条件的条件,即EXITS子句中查询中至少有一条记录,条件是id_user与QUERY1查询中的id_user相同..我希望这有点道理..

如果您提供User表的结构,我可能会为您调整一下。顺便说一句,使用那些毯子SELECT *语句不是一个好主意..

答案 2 :(得分:0)

我认为你可以简化查询。它有几个好奇心。首先,查询不使用正确的连接语法。其次,查询使用having子句来过滤select的别名。在这种情况下,我建议使用子查询。

看起来您正在尝试让两个非常相似的查询定义的“组”中的用户(只有where子句不同)。您可能正在寻找以下内容:

select t.*
from (SELECT *, DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age,
             (case when cp >= 1 AND cp <= 3000 AND sexe = 'M' AND UU.id_mailing = 6 then 'FirstGroup'
                   when cp >= 1 AND cp <= 3000 AND sexe = 'M' AND UU.id_mailing = 7 then 'SecondGroup'
              end) as thegroup
      FROM user U join user_utilisation UU 
           on U.id_user = UU.id_user
     ) t
where thegroup is not null and age between 1 and 100
GROUP BY U.id_user
having max(thegroup) <> min(thegroup)
ORDER BY nom, prenom

having子句是说用户同时在两个组中的简单方法。