2009-10-22 64 views
3

首先我真的不是在SQL很大,隨着中說的,開始的問題:添加一些邏輯來SQL查詢

可以說我有一個表叫能力。 在這個例子中,能力有一個ID,PersonID,文本。

比方說,我做了一個搜索,在其中指定我想清楚地列出每個有能力'飛','駕車','唱'但沒有'打','滑板'

有沒有辦法編寫這樣的查詢,最後只會返回符合上述語句的行?表格和它的內容純粹是虛構的,我可能會添加,因此,這個奇怪的:P

我真的很感謝幫助,因爲它是一個相當複雜的數據庫搜索工具。

感謝

+0

你希望所有的能力(包括或排除)或任何包括列表和任何排除列表的?對需求和工作有所不同。 – Murph 2009-10-22 15:27:42

回答

5
SELECT a.PersonId 
FROM Abilities a 
JOIN Abilities b ON (a.PersonId = b.PersonId AND b.text = 'Drive') 
JOIN Abilities c ON (a.PersonId = c.PersonId AND c.text = 'Sing') 
LEFT JOIN Abilities d ON (a.PersonId = d.PersonId AND d.text = 'Flight') 
LEFT JOIN Abilities e ON (a.PersonId = e.PersonId AND e.text = 'Skateboard') 
WHERE a.text = 'Fly' AND d.Id IS NULL and e.Id IS NULL 

我看到你有幾個答案,試圖在同一個能力實例上同時執行IN和NOT測試,但這不能工作 - 你顯然需要測試單獨的能力實例,從而需要這個多重自我-加入!

+0

+1 ...很高興我沒有嘗試這個,一如既往的好回答 – 2009-10-22 15:30:05

+0

非常感謝,非常有幫助 – 2009-10-23 08:46:09

0

沒有指定的數據庫服務器,但我知道這工作在SQL Server

SELECT a1.ID, a1.PersonID, a1.Text 
FROM Abilities a1 
WHERE a1.Text IN ('Fly', 'Drive', 'Sing') 
AND NOT EXISTS (SELECT ID 
       FROM Abilities a2 
       WHERE a2.ID = a1.ID 
       AND a2.Text IN ('Fight', 'Skateboard')) 
1

有許多方法來解決這個問題。我已經選擇了一個應該可讀的,但不一定能夠保持很多變化的。

WITH Fliers AS (
    SELECT PersonID 
    FROM Abilities 
    WHERE Text = 'Fly' 
), 
Drivers AS (
    SELECT PersonID 
    FROM Abilities 
    WHERE Text = 'Drive' 
), 
Singers AS (
    SELECT PersonID 
    FROM Abilities 
    WHERE Text = 'Sing' 
), 
Fighters AS (
    SELECT PersonID 
    FROM Abilities 
    WHERE Text = 'Fight' 
), 
Skateboarders AS (
    SELECT PersonID 
    FROM Abilities 
    WHERE Text = 'Skateboard' 
) 
SELECT * 
FROM People 
INNER JOIN Fliers 
    ON Fliers.PersonID = People.PersonID 
INNER JOIN Drivers 
    ON Drivers.PersonID = People.PersonID 
INNER JOIN Singers 
    ON Singers.PersonID = People.PersonID 
LEFT JOIN Fighters 
    ON Fighters.PersonID = People.PersonID 
LEFT JOIN Skateboarders 
    ON Skateboarders.PersonID = People.PersonID 
WHERE Fighters.PersonID IS NULL 
    AND Skateboarders.PersonID IS NULL 

但是有很多方法可以給這隻貓蒙皮。

大部分的解決方案在這裏使用一個簡單的IN,NOT IN,但他們不會給我看你期待的結果 - 即誰擁有自駕遊,又唱又既不能戰,NOR滑板

3

根據實際的數據和查詢參數,沒有自連接的方法可能會更有效。我希望這可以對錶進行單次完整掃描,而連接方法可能會執行很多索引查找。

SELECT personID FROM 
(
SELECT personID, 
     SUM(CASE WHEN text IN ('Fly','Drive','Sing') THEN 1 ELSE 0 END) good_stuff, 
     SUM(CASE WHEN text IN ('Fight','Skateboard') THEN 1 ELSE 0 END) bad_stuff 
    FROM abilities 
    GROUP BY personID 
) 
WHERE good_stuff = 3 and bad_stuff = 0 
+0

取代嵌套查詢,having子句也可以工作,但它必須重複'SUM能夠使用別名。 – Thorsten 2009-10-22 19:51:42

1
SELECT * FROM (SELECT PERSONID, COUNT(SKILLS) FROM DUMMY WHERE SKILLS IN ('FLY','DRIVE','SING') GROUP BY PERSONID HAVING COUNT(*)=3) A 

WHERE PERSONID NOT IN 

(SELECT DISTINCT PERSONID FROM DUMMY WHERE SKILLS IN ('FIGHT','SKATEBOARD') ) 
+1

歡迎來到Stack Overflow!請[格式化您的代碼](http://meta.stackexchange.com/a/22189)以提高可讀性。 – AHiggins 2015-07-20 15:28:53

+1

另外,我們希望儘可能[避免只使用代碼的答案](http://meta.stackexchange.com/a/148274)。一個非常好的答案通常包括解釋和描述你正在做什麼,爲什麼!包括這些幫助使網站更好的細節,並使自己的答案更有用。 – AHiggins 2015-07-20 15:30:54