2013-03-05 47 views
1

預先做了兩件事。首先我有解決我的問題。我在這裏提供指導,看看它是否是一個好的解決方案,如果我可以做得更好。其次,我想先道歉我的無知!我是一個建立一個剛剛進入SQL的網站的java人。我仍然有很多學習要做,這就是爲什麼我在這裏尋找指導。子查詢的可擴展性和可能的​​替代方案

我有三個表處理這個查詢。

  1. 用戶 - 有關網站
  2. 朋友上所有用戶的基本資料 - 擁有兩個人誰是朋友
  3. 跨越式的用戶ID的 - 認爲像Facebook塗鴉牆進步的。任何用戶都可以在他們的牆上或朋友牆上發佈步伐更新。

用於查找所有用戶朋友並返回其ID號的SQL語句如下所示。

SELECT user.id 
FROM user 
INNER JOIN friends ON user.id = friends.user2 WHERE friends.user1 = 1 
UNION ALL 
SELECT user.id FROM user 
INNER JOIN friends on user.id = friends.user1 WHERE friends.user2 = 1 

現在我的目標是有一個像活體飼料的facebook。因此,任何時候用戶發佈一個大步,他們的所有朋友都會被告知。所以我知道第一步是讓所有的用戶朋友,我這樣做以上。所以現在我想將這些朋友鏈接到跨步表。

在步幅表中,有sourceUserId(寫出步幅的人)和recipientId(接收步幅的人)的列。所以如果你在你自己的電路板上編寫的,你的ID是2,那麼這兩列都是2。我的目標是創建一個SQL語句,可以查找所有用戶朋友,以及這些朋友在他們的董事會和朋友董事會中發佈的所有帖子。

經過太多的搜索,我發現了關於SQL子查詢,並得出了一個結果。問題是我是新的,不知道這是否是一個好的結果,因爲我今天才知道這些東西!我害怕可擴展性,並且一旦擁有100,1000或甚至100,000個用戶,這件事情就會失靈!所以我的問題是,

  1. 是一個子查詢這裏最好的選擇?如果是這樣,我做得對嗎?如果不是我該如何解決這個問題
  2. 是否有任何列我應該索引以加快此查詢。
  3. 你有什麼其他的建議,關於如何提高我的未來的一個新的SQL查詢的傢伙

這裏是我想出了這個代碼!

SELECT * FROM stride WHERE sourceUserId = ANY 
(
    SELECT user.id 
    FROM user 
    INNER JOIN friends ON user.id = friends.user2 WHERE friends.user1 = 1 
    UNION ALL 
    SELECT user.id FROM user 
    INNER JOIN friends on user.id = friends.user1 WHERE friends.user2 = 1 
) 
AND recipientId = ANY 
(
    SELECT user.id 
    FROM user 
    INNER JOIN friends ON user.id = friends.user2 WHERE friends.user1 = 1 
    UNION ALL 
    SELECT user.id FROM user 
    INNER JOIN friends on user.id = friends.user1 WHERE friends.user2 = 1 
) 

UPDATE:了一堆新的知識我已經能夠得到一個堅實的SQL statment我活飼料是0.0009秒!這裏是任何有興趣的人。

SELECT stride.id AS link, sourceUser.userName, sourceUser.displayName, recipientUser.fName AS recipient, sourceUser.currentDefault, stride.content, stride.timestamp, 

CASE WHEN (recipientId = sourceUserId) THEN "personalStride" ELSE "friendStride" END AS notType 
FROM stride 

INNER JOIN user AS sourceUser ON sourceUser.id = stride.sourceUserId 
INNER JOIN user AS recipientUser ON recipientUser.id = stride.recipientId 

WHERE sourceUserId = ANY 
(
    SELECT CASE WHEN user1 = 1 
    THEN user2 ELSE user1 END AS sourceUserId 
    FROM friends 
    WHERE user1 = 1 OR user2 = 1 
) 
AND recipientId = ANY 
(
    SELECT CASE WHEN user1 = 1 
    THEN user2 ELSE user1 END AS sourceUserId 
    FROM friends 
    WHERE user1 = 1 OR user2 = 1 
) 
ORDER BY timestamp desc 

回答

0

你不需要一個聯盟:

SELECT 
    CASE 
     WHEN f.user1=u.id 
     THEN f.user2 
     ELSE f.user1 
    END AS f_id 
FROM user 
    JOIN friends AS f 
     ON f.user1=u.id OR f.user2=u.id 
WHERE u.id = 1 

其實你並不需要用戶或者(假設,當然,在朋友表中的每個ID在用戶表的匹配)加盟,我只是添加它,所以我們可以有很好的「u.id」而不是幻數。

SELECT 
    CASE 
     WHEN f.user1=2 
     THEN f.user2 
     ELSE f.user1 
    END AS f_id 
FROM friends AS f 
WHERE f.user1=2 OR f.user2=2 

http://sqlfiddle.com/#!2/afb4d/8

編輯: 至於其他查詢該事項比較複雜一點我結束了這樣的查詢:

SELECT s.id,s.sourceUserId,s.recipientId 
FROM STRIDE as s 
    JOIN friends AS f 
     ON 
      (
      ((s.sourceUserId=f.user1 OR s.recipientId=f.user1) AND f.user2=1) OR 
      ((s.sourceUserId=f.user2 OR s.recipientId=f.user2)AND f.user1=1) 
     ) 
GROUP BY s.id,s.sourceUserId,s.recipientId 
HAVING COUNT(*)=2 OR s.sourceUserId=s.recipientId; 

http://sqlfiddle.com/#!2/83363/1 我們選擇該行如果源或收件人是我們用戶的朋友,並且我們總結它,如果該行顯示兩次,則表示源和收件人都是朋友。我們還會選擇source = recipient的地方,因爲它們只會顯示一次。

子查詢是有用的,但它們可以避免,除非你需要兩個不同的聚合和通常避免他們會更快。 O男孩。

+0

O男孩。這對我來說看起來像一門外語。我需要了解一下現在的情況 – gmustudent 2013-03-05 01:46:07

+0

這裏發生了什麼 - 然後是f.user2 else f.user1 - 我瞭解什麼時候發生了什麼,但接下來的兩行是什麼? – gmustudent 2013-03-05 02:01:44

+0

@gmustudent它告訴哪個字段使用,如果user1是我們的用戶然後顯示user2 else顯示user1 – 2013-03-05 02:10:19