2012-12-14 47 views
12

我有3個表數據如下:MYSQL錯誤的結果輸出

1表稱爲連接,其中connections.username1是誰遵循和connections.username2是一個誰是跟着一個。

它具有以下行:

connections.username1 | connections.username2 
     mikha   |   guy 
     guy    |   maricela 
     maricela  |   guy 

第二臺名爲問題。它有一個名爲questions.asker_username的提問者和一個接收questions.target_username問題的人的列。當提問者被稱爲「sys.tem」並且目標被稱爲「every.one」時,它被認爲是全局性問題並且可以被所有成員回答。

匿名用戶可能會問,他們的IP記錄爲asker_username

它具有以下行:

questions.id | questions.asker_username | questions.target_username | questions.question 
    1   |  mikha    |  guy     | what's your name?        
    2   |  mikha    |  maricela   | What's your age? 
    3   |  guy     |  mikha    | what's your name? 
    4   |  maricela   |  guy     | favorite food? 
    5   |  xx.xx.xxx.xx  |  mikha    | favorite pet? 
    6   |  xx.xx.xxx.xx  |  guy     | first name? 
    7   |  xx.xx.xxx.xx  |  maricela   | first name? 
    8   |  sys.tem    |  every.one   | what's ur name? 
    9   |  sys.tem    |  every.one   | favorite movie? 
10   |  sys.tem    |  every.one   | favorite game? 

第三表被稱爲答案。答案表中的id與問題ID相同。此表有一個id和用戶名和答案的列。

answers.id | answers.username | answers.answer 
    1  |  guy   | my name is guy 
    2  |  maricela  | my name is maricela 
    3  |  mikha  | my name is mikha 
    4  |  guy   | pizza   
    8  |  guy   | guy is my name 
    8  |  maricela | maricela is my name 
    9  |  maricela | avatar 

我想它結合了與 「mikha」,他跟隨人以下條件的查詢:

1)questions.asker_username不是 「mikha」

2)questions.target_username要麼是「mikha 「或他遵循的任何用戶。

3)如果questions.target_username等於「every.one」並回答「mikha」,則顯示該問題。

4)如果questions.target_username等於「every.one」,並由任何「mikha」跟隨的人回答,則顯示問題及其答案。如果沒有「mikha」關注用戶的回答,請不要顯示該問題。

5)如果questions.target_username等於「every.one」並且根本沒有人回答,則顯示該問題一次。

6)如果questions.target_username等於「every.one」並且沒有被「mikha」回答並且沒有被任何他回答的人回答,則只顯示一次問題。

我用下面的查詢:

SELECT questions.id,answers.id,questions.asker_username,questions.target_username, 
    answers.username,questions.question,answers.answer 
FROM questions 
    LEFT JOIN answers ON (questions.id = answers.id) 
    LEFT JOIN connections ON connections.username1 = 'mikha' 
     AND (questions.target_username = connections.username2 
      OR questions.asker_username = connections.username2 
      OR connections.username2 = answers.username) 
WHERE questions.asker_username <> 'mikha' 
    AND (questions.target_username = 'mikha' 
     OR questions.target_username = connections.username2 
     OR (questions.target_username = 'every.one' 
      AND (answers.username = 'mikha' 
       OR answers.username = connections.username2 
       OR answers.username IS NULL) 
      ) 
     ) 
GROUP BY questions.id,answers.username 

結果我想到:

questions.id | answers.id | questions.asker_username | questions.target_username | answers.username | questions.question | answers.answer 
    3  |  3  |  guy    |   mikha   | mikha   | what's your name? | my name is mikha 
    4  |  4  |  maricela   |   guy    | guy   | favorite food?  | pizza 
    5  |  5  |  xx.xx.xxx.xx  |   mikha   | NULL   | favorite pet?  | NULL 
    6  |  6  |  xx.xx.xxx.xx  |   guy    | NULL   | first name?  | NULL   
    8  |  8  |  sys.tem   |   every.one   | NULL   | what's ur name? | NULL 
    8  |  8  |  sys.tem   |   every.one   | guy   | what's ur name? | guy is my name 
    9  |  9  |  sys.tem   |   every.one   | NULL   | favorite movie? | NULL  
    10  |  10 |  sys.tem   |   every.one   | NULL   | favorite game?  | NULL 

結果我居然得到:

questions.id | answers.id | questions.asker_username | questions.target_username | answers.username | questions.question | answers.answer 
    3  |  3  |  guy    |   mikha   | mikha   | what's your name? | my name is mikha 
    4  |  4  |  maricela   |   guy    | guy   | favorite food?  | pizza 
    5  |  5  |  xx.xx.xxx.xx  |   mikha   | NULL   | favorite pet?  | NULL 
    6  |  6  |  xx.xx.xxx.xx  |   guy    | NULL   | first name?  | NULL   
    8  |  8  |  sys.tem   |   every.one   | guy   | what's ur name? | guy is my name   
    10  |  10 |  sys.tem   |   every.one   | NULL   | favorite game?  | NULL 

我建http://sqlfiddle.com/#!2/29929e/1方案展示你實際得到的結果

謝謝:)

+0

這是非常好的問題描述,的確,但是由於SO規則,什麼是問題(我沒有看到任何問號)? – shadyyx

+0

什麼是實現預期結果的正確查詢?這讓我瘋狂了一個多星期:(謝謝:) –

+1

要求4和6相互矛盾。 4說:如果沒有人mikha的回答,請不要回答。 6說:如果沒有人回答,請回答。 –

回答

2

問題是 - 在某些情況下 - 當只有一個匹配的答案存在時,您想要顯示一個問題兩次。我引述:

所以,我想表明它只有一次「mikha」無論是回答與否,並再次顯示它會在每次由任何人的「mikha回答說:」時間如下

這種重複使事情變得非常困難。

我試圖解決這個與UNION它似乎工作。但是,我還沒有完全理解你的要求......

無論如何,在這裏我們去:

select * from 
(
    select 
    q.id as q_id, a.id as a_id, q.asker_username, 
    q.target_username, a.username, q.question, a.answer 
    from 
    questions q 
    left outer join answers a on q.id = a.id 
    where 
    q.asker_username <> 'mikha' 
    and 
    (
     q.target_username = 'mikha' 
     or q.target_username in 
     (select username2 from connections where username1 = 'mikha') 
     or 
     (
     q.target_username = 'every.one' 
     and 
     (
      a.username = 'mikha' 
      or a.username in 
      (select username2 from connections where username1 = 'mikha') 
      or a.id is null 
     ) 
    ) 
    ) 
    union 
    select 
    q.id as q_id, NULL as a_id, q.asker_username, 
    q.target_username, NULL, q.question, NULL 
    from 
    questions q 
    where 
    q.asker_username <> 'mikha' 
    and q.target_username = 'every.one' 
    and not exists (select id 
        from answers 
        where 
         id = q.id 
         and username = 'mikha' 
        ) 
) r 
order by q_id; 

測試直播:
With answer from mikha for question 8
Without answer from mikha for question 8

+0

我犯了一個錯誤,只是編輯了我原來的問題。我有第8行mikha回答。我刪除它以避免混淆。現在第8行應該顯示兩次,一次是爲mikha,因爲他還沒有回答,一次是爲了男人,因爲他跟着mikha,他已經給出了答案。 maricela答案被忽略,因爲她沒有跟隨mikha –

+0

@MichaelSamuel:請檢查更新的版本。 –

+0

這一個工作得很好:)但沒有任何方式來做沒有聯合和子查詢的上述查詢?縮放時,兩者都會影響性能。謝謝:) –

5

OK,讓我們從最簡單的一個(你的第一條規則)開始:

SELECT q.id, a.id, q.asker_username, q.target_username, a.username, q.question, a.answer 
FROM questions q 
    LEFT JOIN answers a ON q.id = a.id 
WHERE q.asker_username <> 'mikha' 
GROUP BY q.id,a.username 

現在讓我們來添加你的第二個規則 - 現在更多的複雜性增加......

SELECT q.id, a.id, q.asker_username, q.target_username, a.username, q.question, a.answer 
FROM questions q 
    LEFT JOIN answers a ON q.id = a.id 
WHERE q.asker_username <> 'mikha' 
    AND q.target_username = 'mikha' 
     OR q.target_username IN (
      SELECT username2 
      FROM connections 
      WHERE username1 = 'mikha' 
     ) 
GROUP BY q.id,a.username 

現在第三個規則(大家通過mikha回答):

SELECT q.id, a.id, q.asker_username, q.target_username, a.username, q.question, a.answer 
FROM questions q 
    LEFT JOIN answers a ON q.id = a.id 
WHERE q.asker_username <> 'mikha' 
    AND q.target_username = 'mikha' 
     OR q.target_username IN (
      SELECT username2 
      FROM connections 
      WHERE username1 = 'mikha' 
     ) 
     OR (q.target_username = 'every.one' AND a.username = 'mikha') 
GROUP BY q.id,a.username 

現在的第四條規則:

SELECT q.id, a.id, q.asker_username, q.target_username, a.username, q.question, a.answer 
FROM questions q 
    LEFT JOIN answers a ON q.id = a.id 
WHERE q.asker_username <> 'mikha' 
    AND q.target_username = 'mikha' 
     OR q.target_username IN (
      SELECT username2 
      FROM connections 
      WHERE username1 = 'mikha' 
     ) 
     OR (q.target_username = 'every.one' AND a.username = 'mikha') 
     OR (q.target_username = 'every.one' AND a.username IN (
      SELECT username2 
      FROM connections 
       INNER JOIN answers ON answers.username = connections.username2 
        AND answers.answers IS NOT NULL 
      WHERE username1 = 'mikha' 
     )) 
GROUP BY q.id,a.username 

第五規則(耶穌!):

SELECT q.id, a.id, q.asker_username, q.target_username, a.username, q.question, a.answer 
FROM questions q 
    LEFT JOIN answers a ON q.id = a.id 
WHERE q.asker_username <> 'mikha' 
    AND q.target_username = 'mikha' 
     OR q.target_username IN (
      SELECT username2 
      FROM connections 
      WHERE username1 = 'mikha' 
     ) 
     OR (q.target_username = 'every.one' AND a.username = 'mikha') 
     OR (q.target_username = 'every.one' AND a.username IN (
      SELECT username2 
      FROM connections 
       INNER JOIN answers ON answers.username = connections.username2 
        AND answers.answers IS NOT NULL 
      WHERE username1 = 'mikha' 
     )) 
     OR (q.target_username = 'every.one' AND a.answer IS NULL) 
GROUP BY q.id,a.username 

而最後一個:

SELECT q.id, a.id, q.asker_username, q.target_username, a.username, q.question, a.answer 
FROM questions q 
    LEFT JOIN answers a ON q.id = a.id 
WHERE q.asker_username <> 'mikha' 
    AND q.target_username = 'mikha' 
     OR q.target_username IN (
      SELECT username2 
      FROM connections 
      WHERE username1 = 'mikha' 
     ) 
     OR (q.target_username = 'every.one' AND a.username = 'mikha') 
     OR (q.target_username = 'every.one' AND a.username IN (
      SELECT username2 
      FROM connections 
       INNER JOIN answers ON answers.username = connections.username2 
        AND answers.answers IS NOT NULL 
      WHERE username1 = 'mikha' 
     )) 
     OR (q.target_username = 'every.one' AND a.answer IS NULL) 
     OR (q.target_username = 'every.one' AND a.username NOT IN (
      SELECT username2 
      FROM connections 
       INNER JOIN answers ON answers.username = connections.username2 
        AND answers.answers IS NOT NULL 
      WHERE username1 = 'mikha' 
     )) 
GROUP BY q.id,a.username 

我認爲,第4條和第6條是有點矛盾(矛盾可以說),並在一個查詢中使用時,它會有相同的效果,如果省略...

我沒有測試任何查詢,但我相信它們可以工作。

+0

Hey Shady :)感謝您的努力,但它給了我相同的輸出結果,現在由於某種原因忽略了第一種情況。你可以在這裏測試sqlfiddle http://sqlfiddle.com/#!2/29929e/101謝謝:) –

+0

@MichaelSamuel對不起,我沒有太多的時間來測試查詢和尋找缺少的部分。請按照我的示例 - 將您的查詢「解體」到最簡單的部分,然後像我一樣添加一個,直到找到您期望的結果。 :-)在構建複雜查詢時始終使用這種技術 - 從最簡單的查詢開始,並一次繼續構建一個步驟。 – shadyyx

+0

相信我...我一直在嘗試這一個多星期沒有用:(有我在查詢中丟失的東西。我無法實現這就是爲什麼我不得不問...感謝:) –

0

我會建議你的出發點的一個主要問題是,你需要連接兩次連接表 - 一次是爲了答案,一次是在回答問題。

下面的代碼給出了它在做什麼的內聯評論。我也同意其他答案,暗示數字ID字段會更好地進行比較 - 並且我還建議在答案表上放置一個獨特的rowid字段(更好的是,將id更改爲question_id,然後將id作爲唯一字段。

SELECT DISTINCT q.id,a.id,q.asker_username,q.target_username,a.username,q.question,a.answer 
FROM questions q 
    /* Answers */ 
    LEFT JOIN answers a ON (q.id=a.id) 
    /* connection entries where the person being followed is the target */ 
    LEFT JOIN (SELECT username2 FROM connections WHERE username1='mikha') c_q 
    ON c_q.username2=q.target_username 
    /* connection entries where the person being followed answered the question */ 
    LEFT JOIN (SELECT username2 FROM connections WHERE username1='mikha') c_a 
    ON c_a.username2=a.username 
    /* Own answers */ 
    LEFT JOIN (SELECT id FROM answers WHERE username='mikha') a_own 
    ON (q.id=a_own.id) 
    WHERE 
    /* Asker not mikha, target is mikha or followed user - rules 1,2 */ 
    (q.asker_username <> 'mikha' 
    AND (q.target_username='mikha' OR c_q.username2 IS NOT NULL)) 
    OR 
    /* sys.tem/every.one, answered by mikha - rule 3 */ 
    (q.target_username='every.one' AND a.username='mikha') 
    OR 
    /* Rules 4, 5 & 6 combine to give "show the answer at least once, and once for every followed user who answered" - here we select any every.one messages where mikha didn't answer and nor did the people he follows */ 
    (q.target_username='every.one' AND a_own.id IS NULL AND c_a.username2 IS NULL); 

它不給你兩行的問題8,但我真的不能明白爲什麼你想這一點。這個問題存在,它不是明確的哪些規則是添加劑,哪些是組合子。如果你可以解釋哪些規則應該「添加」一行,而不僅僅是提供另一個顯示行的理由,那麼也許我們可以爲你提供問題8的額外行。

+0

好吧..很簡單..問題主要在於問題是全球問題時(目標=每一個)。用戶(mikha)可能會跟隨許多用戶,如1000個用戶。在這種情況下,全球性問題將在Mikha的飼料上出現1000次,這是沒有意義的。這就是爲什麼我只想在回答時才顯示它以避免重複。我想再次展示它一次,以便「mikha」可以回答它,或者如果mikha回答這個問題,回答問題(這就是爲什麼要顯示第8行兩次,一次是mikha,一次是因爲人回答mikha跟着他)。 –

+0

另一種情況是,網站上的任何成員都沒有回答全局問題,只顯示一次,以便「mikha」可以回答它(這是第10行)。另外一個例子,當mikha沒有回答他所關注的人時,它也顯示了一次mikha可以回答(這是第9行) –