2013-01-21 91 views
4

我一直在嘗試將一天中最好的部分刪除,因爲它不被mysql支持。如果任何人都可以提供一些指針,這將是非常有用的。mysql 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 = 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(一個或多個),但這裏是我現在所擁有的:

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_mailingdate

+0

對不起,我肯定可能是錯的,但是怎麼能這樣一個路口返回任何結果呢?如果第一個記錄的id_mailing = 6,則選擇一條記錄;如果第二個記錄的id_mailing = 7,則記錄被選中。我認爲不可能是兩個。 – Aioros

+1

你能否向我們提供一個你試圖擺脫查詢的例子? – ESG

回答

2

解釋您的疑問,在我看來:

  1. 你想誰參加mailing_id 6和7的所有用戶(這就是爲什麼你在做INTERSECT,是嗎?)。
  2. 您想按標準限制這些用戶並執行年齡計算。

如果我對你的意圖的解釋是正確的(並不一定是這樣!),你不需要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 
+0

似乎是我正在尋找。 TY! – Narcil

+0

很高興幫助!如果你認爲這個問題已經回答了你的問題,你可以通過點擊答案右上角的大複選標記來「接受」它作爲答案。 – DWright

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(...)子句充當過濾器,類似於您正在使用前交叉。我們的想法是,您只希望從查詢QUERY1中選擇那些滿足以下條件的記錄:EXITS子句中查詢中至少有一條記錄,條件是id_user與QUERY1查詢中的id_user相同..我希望這是有道理的..

如果你要提供用戶表的結構,我可能會調整它一點。順便說一句,使用這些毛毯SELECT *語句是不是一個好主意..

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條款是說,用戶在這兩個組的速記方式。