1

前面有两件事。首先,我有一个解决我的问题的方法。我在这里寻求指导,看看它是否是一个好的解决方案,以及我是否可以做得更好。其次,我想为我的无知道歉!我是一个 Java 人,正在建立一个刚刚进入 SQL 的站点。我还有很多学习要做,这就是我在这里寻求指导的原因。

我有三个处理这个查询的表。

  1. 用户 - 网站上所有用户的基本信息
  2. Friends - 保存两个朋友的用户 ID
  3. 大步 - 想想像 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(编写步幅的人)和接收者Id(接收步幅的人)的列。因此,如果您在自己的板上写字并且您的 id 为 2,那么这两个列都是 2。我的目标是创建一个 SQL 语句,可以找到所有用户的朋友,以及这些朋友在他们的董事会和他们的朋友董事会上发表的所有帖子。

经过太多的谷歌搜索后,我发现了 SQL 子查询并得出了一个结果。问题是我是新手,不知道这是不是一个好结果,因为我今天才知道这些东西!我对可扩展性感到害怕,如果我拥有 100、1,000 甚至 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
) 

更新:有了一堆新知识,我已经能够为我的实时提要获得一个可靠的 SQL 语句,即 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
4

1 回答 1

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 的那些,因为它们只会出现一次。

子查询很有用,但可以避免使用,除非您需要两个不同的聚合,并且通常避免使用它们会快得多。

于 2013-03-05T01:37:27.493 回答