我需要搜索赠送用户的朋友发送的更新。
有一个名为friendship
的表格。它有一个名为profile1
的列,另一个名为profile2
。它代表了这个网络系统中两个用户之间的友谊,友谊是两个赠送ID的存在,无论在什么位置。因此,ID为1的个人资料可能包含2个朋友,个人资料ID为id 2,ID为3,如下所示:
friendship
profile1 profile2
1 2 <--
3 1 <--
2 5
...
现在我想搜索某些用户的朋友发送的更新。有这个表update
update
id content time profile
1 A text ... 2
2 A text ... 2
3 A text ... 3
4 A text ... 2
5 A text ... 3
6 A text ... 2
7 A text ... 10
8 A text ... 11
如果我的个人资料/用户被id 1标识,并且它只有2个朋友(由id 2和3标识的个人资料),而且我需要我的搜索只返回每个用户的2个结果,我的SELECT必须返回更新1,2,3和5.
最好更新应按其作者进行分组,如果我可以设置在此搜索中要考虑的不同配置文件的数量,那将是很好的(例如,如果配置文件1有10个朋友,我只想要3个配置文件的更新,最近必须首先出现。)
你知道我怎么能做到这一点?
非常感谢你!@EDIT
这将返回配置文件1的朋友发送的所有更新。但我不确定我是否在正确的方向
SELECT u.*
FROM `update` u
INNER JOIN friendship f1 ON f1.profile1 = u.author
WHERE f1.profile2 =1
UNION
SELECT u.*
FROM `update` u
INNER JOIN friendship f2 ON f2.profile2 = u.author
WHERE f2.profile1 =1
答案 0 :(得分:1)
我建议在一个事务中为每个作者执行一系列查询,这样就不需要进行分组 - 您可以简单地将结果附加到SQL之外。
SELECT * FROM `update` WHERE
profile IN (SELECT profile2 FROM `friendship` WHERE profile1=1) OR
profile IN (SELECT profile1 FROM `friendship` WHERE profile2=1);
答案 1 :(得分:1)
如果您愿意在两个查询中执行此操作,则可以这样做。首先,根据您的约束条件获取最近发布的三个配置文件:
-- Get the three latest updated profiles from here.
-- (we can't use a CTE because MySQL doesn't support
-- them yet).
SELECT DISTINCT p.profile FROM
(
SELECT ui.profile, ui.time FROM
(
SELECT u.profile, u.time
FROM `update` u
INNER JOIN `friendship` f ON f.profile2 = u.profile
WHERE f.profile1 = 1
UNION ALL
SELECT u.profile, u.time
FROM `update` u
INNER JOIN `friendship` f ON f.profile1 = u.profile
WHERE f.profile2 = 1
) ui ORDER BY ui.time DESC
) p LIMIT 0, 3;
从该查询中获取三个个人资料ID,并将其替换为以下查询中的<id1>
,<id2>
和<id3>
-- Use a union to get the result set back
(SELECT a.content, a.time, a.profile FROM `update` a
WHERE a.profile = <id1>
ORDER BY a.time DESC
LIMIT 0, 2)
UNION ALL
(SELECT a.content, a.time, a.profile FROM `update` a
WHERE a.profile = <id2>
ORDER BY a.time DESC
LIMIT 0, 2)
UNION ALL
(SELECT a.content, a.time, a.profile FROM `update` a
WHERE a.profile = <id3>
ORDER BY a.time DESC
LIMIT 0, 2);
如果返回的配置文件少于三个,请删除PHP代码中的部分查询,或者将WHERE子句设置为0之类,以便始终评估为错误(假设您的配置文件ID不为零) )
如果您希望每个配置文件获得更多或更少的结果,则可以更改上面限制条款中的2。
示例SQL小提琴:http://sqlfiddle.com/#!2/22e57/1(更新小提琴以使内容更有意义并使用时间)
答案 2 :(得分:0)
试试这个sqlFiddle
SELECT T1.profile,T1.content,T1.time
FROM
(SELECT UPD.profile,UPD.content,UPD.time,
IF (@prevProfile != UPD.profile,@timeRank:=1,@timeRank:=@timeRank+1) as timeRank,
@prevProfile := UPD.profile
FROM
(SELECT UP.profile,UP.content,UP.time
FROM
(SELECT profile,max(time) as latestUpdateTime
FROM friendship F INNER JOIN updates U
ON (F.profile1 = 1 AND U.profile = profile2) /* <-- specify profile on this line */
OR(F.profile2 = 1 AND U.profile = profile1) /* <-- specify profile on this line */
GROUP BY profile
ORDER BY latestUpdateTime DESC
LIMIT 3 /* limit to 3 friends profiles that have the most recent updates */
)as LU
INNER JOIN updates UP
ON (UP.profile = LU.profile)
ORDER BY profile,time DESC
)as UPD,(SELECT @prevProfile:=0,@timeRank:=0)variables
)T1
WHERE T1.timeRank BETWEEN 1 AND 2 /* grab 2 lastest updates for each profile */
ORDER BY T1.time DESC
在我的示例中,个人资料ID 1有超过3个朋友,但我只抓住了3个最近更新的朋友。
上述查询的解释。
LU
抓取3个个人资料,这些资料是个人资料ID为1的朋友,可以进行最新更新。
UPD
抓取属于这3个朋友的所有内容。
T1
为每个内容返回内容以及timeRank
个数字,从每个个人资料的time DESCENDING
开始向上计数
最后我们只为每个配置文件抓取2个内容更新
然后我们最终根据TIME从最近开始对这些更新进行订购。