复杂的MySQL计数使用连接

时间:2014-04-30 03:29:36

标签: php mysql

基本上,正在发生的事情是有一个表,用户名(UID)跟踪到企业的签到(BID)。 $ startday =当天的开始

Checkins:
 ID | UID | BID | DATE

然后有第二张表跟踪朋友。用户可以是SENDER或RECIEVER

Friends:
 SENDER | RECIEVER | STATUS

我要做的是计算来自任何朋友的签到数量。所以(伪代码)

(if(SENDER = UID) AND (RECEIVER exists in checkins) AND (DATE > $startday)) OR
(if(RECEIVER = UID) AND (SENDER exists in checkins) AND (DATE > $startday))

然后计算这些结果。我知道我需要做某种加入,但我真的不知道从哪个开始这个设计。我很感激任何帮助...

2 个答案:

答案 0 :(得分:0)

试试这个

SELECT COUNT(1) FROM Checkins ch
JOIN Friends fr
ON (fr.SENDER = ch.UID OR fr.RECIEVER = ch.UID)
WHERE ch.DATE = '$startday'

答案 1 :(得分:0)

免责声明:这根本不是很漂亮,可能会做得更整齐,我没有声称它的性能,只是试图给你一个起点,假设我正确理解了这个问题

假设:我假设了以下内容:

  • 朋友的定义是处于SENDER或RECEIVER
  • 之间的任何关系
  • 您想要计算一个人共有多少朋友已经签到
  • 您可以添加自己的WHERE子句来指定要检查的日期范围

答案:以下查询对我有用

SELECT COUNT(*) FROM checkins
INNER JOIN 
(
    SELECT DISTINCT friend FROM 
    (
        SELECT receiver AS friend FROM Friends
            WHERE sender = 1
        UNION ALL
        SELECT sender AS friend FROM Friends
            WHERE receiver = 1
    ) AS t 
) AS allfriends
    ON checkins.uid = allfriends.friend

示例数据:我使用如下

签到

ID          UID         BID         Date
----------- ----------- ----------- ----------
1           1           1           NULL
2           2           1           NULL
3           3           1           NULL
4           4           1           NULL
5           5           1           NULL
6           6           1           NULL
7           1           1           NULL
8           2           1           NULL
9           3           1           NULL
10          4           1           NULL

sender      receiver    status
----------- ----------- -----------
1           2           NULL
1           3           NULL
1           4           NULL
2           3           NULL
2           5           NULL
2           6           NULL
3           1           NULL
2           1           NULL

说明:我会将其分解,以便您可以轻松理解(您可以单独运行这些内容以查看结果)。

首先,我得到了一个用户朋友的所有ID列表,他们是发件人(对于UID 1)。

        SELECT receiver AS friend FROM Friends
            WHERE sender = 1

结果:

friend
-----------
2
3
4

然后又是他们的接收者。

        SELECT sender AS friend FROM Friends
            WHERE receiver = 1

结果:

friend
-----------
3
2

然后UNION ALL他们一起得到一个包含重复项的列表。

        SELECT receiver AS friend FROM Friends
            WHERE sender = 1
        UNION ALL
        SELECT sender AS friend FROM Friends
            WHERE receiver = 1

结果:

friend
-----------
2
3
4
3
2

删除了执行DISTINCT子选择

的重复项
    SELECT DISTINCT friend FROM 
    (
        SELECT receiver AS friend FROM Friends
            WHERE sender = 1
        UNION ALL
        SELECT sender AS friend FROM Friends
            WHERE receiver = 1
    ) AS t 

结果:

friend
-----------
2
3
4

最后,我根据使用INNER JOIN的用户ID将checkins表加入了不同朋友列表。 INNER JOIN将从checkins中提取uid所有结果,其中allfriends也存在于我们的子选择6 中。添加COUNT(*)可以计算所有行数。

完整查询的结果:

WHERE

然后,您可以使用BETWEEN将日期选择包装在此周围,以便仅根据需要获得两个日期的结果{{1}}。