MySQL --- установить операции MINUS и INTERSECT на одной таблице - PullRequest
0 голосов
/ 02 мая 2018

Нам необходимо отслеживать изменение членства в наборе с течением времени. Я могу объяснить нашу проблему с помощью следующей простой таблицы:

+-----------+------------------+------+-----+---------+----------------+
| 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 голосов
/ 02 мая 2018

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> Y, то это будут полученные члены; если 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"
;
...