2015-02-23 88 views
3

我想了解如何有效地將謂詞邏輯轉換爲SQL查詢。我被困在:SQL:從謂詞邏輯到SQL SELECT

For all P(x), (for all P(y), (Knows(x,y) -> Likes(x,y))) 

,我還翻譯成:

-exists P(x), (exists P(y), (Knows(x,y) /\ -Likes(x,y))) 

使用的 '公式':

for all x, (A -> B) <=> -exists x, (A /\ -B); for all x, (A) <=> -exists x, (-A) 

隨着開始錯的概率,這裏是最初的口齒:

Write a query that returns the name of all persons that like everyone they know. 

W這裏Knows和Like表都不是對稱的,只是包含Person表的外鍵,因此表示Person X Knows/Like Person Y.

SQL SELECT查詢如何看起來像上面那樣?

我都試過,但不起作用:

SELECT P.name 
FROM Persons P 
WHERE NOT EXISTS (
    SELECT * 
    FROM Knows K 
    WHERE K.personB_id NOT IN (
     SELECT L.personB_id 
     FROM Likes L 
     WHERE K.personA_id = L.personA_id 
     AND K.personB_id <> L.personB_id)) 
+0

不錯的問題。 SQL中有多種解決方案,最有效的解決方案不一定是謂詞邏輯的直接翻譯。但是,我想知道爲什麼你沒有爲特定的固定'x'應用更明顯的重寫'forall P(y)(〜knows(x,y)\/likes(x,y))'。 – 2015-02-23 10:23:28

+0

@JeroenMostert A-> B <=> -A \/B也是我事先知道的。然而,在我的課程中,我們被推薦使用我寫的那些「公式」,所以我試圖這樣做。在任何情況下,查詢如何看起來像「forall P(y)(〜knows(x,y)\/likes(x,y))」? – Dimebag 2015-02-23 10:28:56

+0

我有(並且不起作用)是:SELECT P.name FROM Persons P WHERE NOT EXISTS(SELECT * FROM Knows K WHERE K.personB_id NOT IN(SELECT L.personB_id FROM Likes L WHERE K.personA_id = L.personA_id和K.personB_id <> L.personB_id)) – Dimebag 2015-02-23 10:30:03

回答

2

找到誰知道,他們不也喜歡的人的人的名單。然後從他們不在該組中的人員中選擇。

SELECT FROM Persons 
    WHERE Persons.ID NOT IN (
     SELECT Knows.PersonA 
     FROM Knows LEFT JOIN Likes 
     ON Knows.PersonA = Likes.PersonA 
     AND Knows.PersonB = Likes.PersonB 
     WHERE Likes.PersonB is null 
    ) 
+0

完美的作品!我沒有想過使用LEFT JOIN和NULL檢查的事實顯然意味着我需要更多練習^^ – Dimebag 2015-02-23 11:01:01