MySQL ---在同一个表上设置操作MINUS和INTERSECT

时间:2018-05-02 16:36:15

标签: mysql set-operations

我们需要跟踪不断变化的集合成员资格。我可以用下面的简单表来解释我们的问题:

+-----------+------------------+------+-----+---------+----------------+
| 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中实现这些逻辑集操作的最优雅方法是什么?

1 个答案:

答案 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"
;