我们需要跟踪不断变化的集合成员资格。我可以用下面的简单表来解释我们的问题:
+-----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| timestamp | varchar(8) | NO | | NULL | |
| member | varchar(4) | NO | | NULL | |
+-----------+------------------+------+-----+---------+----------------+
SELECT *操作的结果如下:
SELECT * FROM My_Table;
+----+-----------+--------+
| id | timestamp | member |
+----+-----------+--------+
| 1 | 20150101 | A |
| 2 | 20150101 | B |
| 3 | 20150101 | C |
| 4 | 20180101 | A |
| 5 | 20180101 | D |
| 6 | 20180101 | E |
+----+-----------+--------+
逻辑上,我们可以使用SET操作MINUS和INTERSECT来了解在一段时间内添加,删除或保留的成员。例如,以下“逻辑”设置操作给出了在20150101和20180101之间添加的成员数:
SELECT member FROM my_table WHERE timestamp = "20180101"
MINUS
SELECT member FROM my_table WHERE timestamp = "20150101";
同样,以下“逻辑”设置操作给出了20150101和20180101之间的成员数量:
SELECT member FROM my_table WHERE timestamp = "20150101"
MINUS
SELECT member FROM my_table WHERE timestamp = "20180101";
以下“逻辑”设置操作给出20150101和20180101之间保留的成员数:
SELECT member FROM my_table WHERE timestamp = "20150101"
INTERSECT
SELECT member FROM my_table WHERE timestamp = "20180101";
在MySQL中实现这些逻辑集操作的最优雅方法是什么?
答案 0 :(得分:1)
LEFT JOIN最有可能满足前两个人的需求,第三个是简单的INNER JOIN。
成员添加
SELECT t1.member
FROM my_table AS t1
LEFT JOIN my_table AS t2 ON t1.member = t2.member AND t2.timestamp = "20150101"
WHERE t1.timestamp = "20180101"
AND t2.id IS NULL -- this filters results to only those members who did not have an entry in t2
;
成员丢失 应该只能交换上面的时间戳值。
使用此通用表格:
SELECT t1.member
FROM my_table AS t1
LEFT JOIN my_table AS t2 ON t1.member = t2.member AND t2.timestamp = Y
WHERE t1.timestamp = X
AND t2.id IS NULL -- this filters results to only those members who did not have an entry in t2
;
该查询基本上使得记录在时间戳X处的成员在时间戳Y处未被记录为存在。如果X>是的,那将是成员获得;如果X<是的,会员会失败。
成员保留
SELECT t1.member
FROM my_table AS t1
INNER JOIN my_table AS t2 ON t1.member = t2.member
AND t2.timestamp = "20150101" -- This condition would be more "properly"
-- part of the WHERE clause's conditions,
-- but (unlike the LEFT JOIN queries) whether it
-- is in the ON or the WHERE will not change the results
WHERE t1.timestamp = "20180101"
;