情况
我的目标是设置一个每年运行的定时任务,根据数据的年龄从数据库中删除某些数据。我可以使用Bash和MySQL的功能。我开始编写了一个bash脚本,但是突然想到,也许只需要一条SQL查询语句就可以完成所有事情。
我更多地是一个程序员,并没有太多处理数据结构的经验,所以我需要一些帮助。
表格/数据结构
此查询所涉及的相关表格和列如下:
注册:
+-----+-------------------+
| Id | Registration_date |
+-----+-------------------+
| 2 | 2011-10-03 |
| 3 | 2011-10-06 |
| 4 | 2011-10-07 |
| 5 | 2011-10-07 |
| 6 | 2011-10-10 |
| 7 | 2011-10-13 |
| 8 | 2011-10-14 |
| 9 | 2011-10-14 |
| 10 | 2011-10-17 |
+-------------------------+
关联客户端:
+-----------+-----------------+
| Client_id | Registration_id |
+-----------+-----------------+
| 2 | 2 |
| 3 | 2 |
| 3 | 4 |
| 4 | 5 |
| 3 | 6 |
| 5 | 6 |
| 3 | 8 |
| 8 | 9 |
| 7 | 10 |
+-----------------------------+
客户端:只有 ID 在这里是相关的。
正如您所见,这是一个简单的多对多关系。一个客户可以有多个与他相关的注册信息,而一个注册信息可以有多个客户。
目标
我需要删除那些在过去5年内没有新注册信息的客户及其所有注册信息。听起来很简单,对吧?
棘手的部分
只要任何其他客户在任何一个注册信息中有新的注册信息,数据就应该被保留。
因此,假设客户A有4个仅包含他自己的注册信息,以及1个自己和客户B的注册信息。这五个注册信息都超过了5年。如果客户B在5年内没有进行新的注册信息,那么一切都应该被删除:客户A的注册信息和记录。如果B 确实在5年内有新的注册信息,所有客户A的数据都应该被保留,包括他自己的旧注册信息。
我的尝试
构建查询时,我大约完成了以下步骤:
DELETE * FROM `Registration` AS Reg
WHERE TIMESTAMPDIFF(YEAR, Reg.`Registration_date`, NOW()) >= 5
AND
(COUNT(`Id`) FROM `Registration` AS Reg2
WHERE Reg2.`Id` IN (SELECT `Registration_id` FROM `AssociatedClient` AS Clients
WHERE Clients.`Client_id` IN (SELECT `Client_id` FROM `AssociatedClient` AS Clients2
WHERE Clients2.`Registration_id` IN -- stuck
#I need all the registrations from the clients associated with the first
# (outer) registration here, that are newer than 5 years.
) = 0 -- No newer registrations from any associated clients
请理解我对SQL的经验非常有限。我意识到即使我已经得到了一些内容,也可以进行大量优化(使用连接等),并且可能甚至不正确。
我卡住的原因是我心中的解决方案需要使用某种循环,而我才刚刚意识到这在这种类型的SQL查询中并不容易实现。
任何帮助都将不胜感激。
AssociatedClient
的表中的示例数据并没有展示这一点。如果我假设以下两条记录可以同时存在于AssociatedClient
表中,那么我的理解是否正确:(2,2), (3,2)
? - RandomSeedWHERE
子句中使用SELECT
。我想你可以使用两个步骤的解决方案 - 使用类似于我的查询模式的SELECT
将要删除的ID放入临时表中,然后执行DELETE * FROM REGISTRATION WHERE REGISTRATION.ID IN TEMPTABLE
。 - Rich Tolley