我目前正在尝试用 MySQL 和 PHP 解决一个复杂的问题。
这是我拥有的表格的示例:
客户名单:
table_clients
Client_ID | Client_Name | Address | Zip Code |
----------|-------------|-----------------|----------|
1 | Mark | 127 Park Ave | 12235 |
2 | John | 6 Freeman Drive | 12899 |
3 | Allan | 450 Clever Rd | 12235 |
服务清单:
table_services
Service_ID | Service_Name | Service_Price |
-----------|--------------|---------------|
1 | Fertilizer | 100.00 |
2 | Bug Spray | 50.00 |
3 | Seeds | 20.00 |
下一个表存储哪个客户端拥有哪些服务(一个或多个)、服务的状态和完成日期(如果适用):
table_jobs
Job_ID | Client_ID | Service_ID | Status | Date_Done |
-------|-----------|------------|--------|------------|
1 | 1 | 1 | done | 2013-05-01 |
2 | 1 | 3 | active | NULL |
3 | 2 | 1 | active | NULL |
4 | 2 | 2 | active | NULL |
5 | 3 | 1 | active | NULL |
6 | 3 | 3 | active | NULL |
现在是棘手的部分。有些服务需要与其他服务有一定的时差。例如,如果一位客户在过去 30 天内收到了肥料,则无法收到种子。为了跟踪这一点,我有第三个表格,其中包含以下信息:
table_time_difference
Service_ID_1 | Service_ID_2 | Time_Diff |
-------------|--------------|-----------|
1 | 3 | 30d |
1 | 4 | 7d |
2 | 4 | 14d |
4 | 5 | 14d |
现在所有内容都存储在数据库中(请记住,可能有数十个服务和数千个客户端),我正在尝试获取是否具有某些服务的客户端行,同时始终尊重时差。
例如:
我希望所有将收到肥料的客户都应该返回:
Client_ID | Client_Name | Zip Code | Job_ID | Service_ID | Service_Name |
----------|-------------|----------|--------|------------|--------------|
2 | John | 12235 | 3 | 1 | Fertilizer |
3 | Allan | 12145 | 5 | 1 | Fertilizer |
现在,如果我想做所有将收到肥料和杀虫剂的客户:
Client_ID | Client_Name | Zip Code | Job_ID | Service_ID | Service_Name |
----------|-------------|----------|--------|------------|--------------|
2 | John | 12235 | 3 | 1 | Fertilizer |
2 | John | 12235 | 4 | 2 | Bug Spray |
如果我想做所有将收到邮政编码 12235 种子的客户:
Client_ID | Client_Name | Zip Code | Job_ID | Service_ID | Service_Name |
----------|-------------|----------|--------|------------|--------------|
3 | Allan | 12235 | 6 | 3 | Fertilizer |
请注意,马克是如何不包括在内的,因为他不满足自上次施肥以来 30 天的要求。
我已经尝试了许多不同的选项与各种 JOINS,但从未找到一个像描述的那样工作的解决方案。我得到的最接近的是通过使用 PHP 生成子查询并将它们加入一个大查询中。
例如,我的一个尝试看起来像这样(对于上面的最后一个预期结果):
SELECT c.Client_ID,
c.Client_Name,
c.Zip_Code,
j.Job_ID,
s.Service_ID,
s.Service_Name
FROM clients c
LEFT JOIN jobs j
ON j.Client_ID = c.Client_ID
LEFT JOIN services s
ON s.Service_ID = j.Service_ID
WHERE s.Service_ID = "1"
&& c.Zip_Code = "12235"
&& c.Client_ID NOT IN (
SELECT Client_ID
FROM jobs
WHERE Status = "done"
&& Date_Done < (UNIX_TIMESTAMP() - 2592000)
)
- 请注意,子查询是由 PHP 脚本生成的,该脚本会查找与请求的服务相对应的限制以及该服务的最小时间差,因为同一服务可能有多个限制,我不知道我是否可以这样做在纯 SQL 中。
现在,上面显示的查询确实适用于那个确切的场景(虽然它很慢),但它会中断并且我无法调整它以适应我的其他需求(包含或排除的多个服务)。
告诉我您是否需要任何其他信息,或者您是否愿意进一步讨论。
非常感谢所有阅读了整个问题(很长)的人,我希望你们中的一些人理解我的需求并可以帮助我!