Альтернативы mysql для 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_user, id_mailing и date.


person Narcil    schedule 21.01.2013    source источник
comment
Извините, я определенно могу ошибаться, но как такое пересечение вообще может возвращать какой-либо результат? В первой выбирается запись, если у нее id_mailing = 6, а во второй, если у нее id_mailing = 7. Не может быть и того, и другого, я думаю.   -  person Aioros    schedule 21.01.2013
comment
Можете ли вы предоставить нам пример того, что вы пытаетесь получить из запроса?   -  person ESG    schedule 21.01.2013


Ответы (3)


Интерпретируя ваши запросы, мне кажется:

  1. Вы хотите получить всех пользователей, которые участвуют в mailing_id 6 и 7 (именно поэтому вы делаете INTERSECT, верно?).
  2. Вы хотите ограничить этих пользователей по критериям и выполнить расчет возраста.

Если моя интерпретация вашего намерения верна (совсем не уверен, что это так!), вам вообще не нужно INTERSECT, вы должны иметь возможность просто выбирать нужных пользователей с нужными вам критериями и ограничивать участие в обе рассылки 6 и 7 через JOIN:

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
person DWright    schedule 21.01.2013
comment
Кажется, это именно то, что я искал. ТЫ! - person Narcil; 22.01.2013
comment
Рад, что помог! Если вы считаете, что это ответ на ваш вопрос, вы можете принять его как ответ, нажав на большую галочку в правом верхнем углу ответа. - person DWright; 22.01.2013

Вы можете попробовать что-то вроде следующего:

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 совпадает с id_user из запроса QUERY1. .. Надеюсь, это имеет смысл..

Возможно, я мог бы немного настроить его для вас, если бы вы предоставили структуру таблицы User. И, кстати, использование этих общих операторов SELECT * не очень хорошая идея.

person Mike Dinescu    schedule 21.01.2013

Я думаю, вы можете упростить запрос. В нем есть несколько курьезов. Во-первых, запрос не использует правильный синтаксис соединения. Во-вторых, запрос использует предложение 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 — это сокращенный способ сказать, что пользователь находится в обеих группах.

person Gordon Linoff    schedule 21.01.2013