我有3个MySQL表,如 -
**tblCampaigns**
campId campName startDate endDate status
1 Campaign1 2016-03-10 00:00:00 2016-03-17 00:00:00 active
2 Campaign2 2016-03-11 00:00:00 2016-03-18 00:00:00 active
**tblServices**
serviceId serviceName
1 Car Washing
2 Car Painting
**tblCampaignServices**
id campId serviceId
1 1 1
2 1 2
我已选择通过自动完成选择向广告系列添加多项服务。我的要求是,当用户键入自动完成以选择要添加到广告系列的服务时,只有那些 serviceName 应出现在建议列表中,这些列表尚未添加到其开始日期和结束日期即将到来的其他广告系列中在当前活动的开始和结束日期之间。我的意思是日期不应与其他广告系列日期相交。此外,serviceName也不应添加到同一个广告系列中。
我做了一半简单的查询,比如获取尚未添加到同一广告系列中的服务 -
select tblServices.serviceId,tblServices.serviceName
from tblServices
LEFT JOIN tblCampaignServices ON (tblServices.serviceId=tblCampaignServices.serviceId
AND tblCampaignServices.campaignId=2)
where ISNULL(tblCampaignServices.id)
首先,是否可以通过单个查询来满足我的要求。如果是,请帮助建立它。如果不是,这是获得这个的最好方法吗?
答案 0 :(得分:1)
以下查询会查找您要查找的内容。
SELECT DISTINCT
tblServices.serviceId,
tblServices.serviceName
FROM tblServices
LEFT JOIN tblCampaignServices ON tblServices.serviceId=tblCampaignServices.serviceId
LEFT JOIN tblCampaigns ON tblCampaigns.campId = tblCampaignServices.campId
WHERE
tblCampaigns.campId IS NULL
OR(
(endDate <
(SELECT startDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2)
OR
startDate >
(SELECT endDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2))
AND serviceName NOT IN
(SELECT serviceName
FROM tblCampaignServices
LEFT JOIN tblServices ON tblServices.serviceId=tblCampaignServices.serviceId
LEFT JOIN tblCampaigns ON tblCampaigns.campId = tblCampaignServices.campId
WHERE
(startDate BETWEEN
(SELECT startDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2)
AND
(SELECT endDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2))
OR
(endDate BETWEEN
(SELECT startDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2)
AND
(SELECT endDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2)))
AND
tblCampaigns.campId <> 2);
这很复杂,所以让我们看看它是如何工作的:
首先,我们加入所有信息,因为我们还需要开始和结束日期来选择允许的服务
我们选择不在广告系列中的所有服务:
tblCampaigns.campId IS NULL
我们选择的活动中的所有服务与当前的服务不重叠,即endDate低于当前的startDate,或者startDate大于当前的endDate:
(endDate <
(SELECT
startDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2)
OR
startDate >
(SELECT
endDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2)
我们从结果集中排除那些广告系列中与当前服务重叠的服务,即当前服务的startDate和endDate之间的startDate或endDate。
serviceName NOT IN
(SELECT serviceName
FROM tblCampaignServices
LEFT JOIN tblServices ON tblServices.serviceId=tblCampaignServices.serviceId
LEFT JOIN tblCampaigns ON tblCampaigns.campId = tblCampaignServices.campId
WHERE
(startDate BETWEEN
(SELECT startDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2)
AND
(SELECT
endDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2))
OR
(endDate BETWEEN
(SELECT startDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2)
AND
(SELECT endDate
FROM tblCampaigns
WHERE tblCampaigns.campId=2)))
我们会排除当前广告系列中已有的服务:
tblCampaigns.campId <> 2
由于结果集将具有重复服务,因为在多个不重叠的广告系列中存在服务,我们将DISTINCT添加到顶部SELECT以避免重复服务。
如果当前广告系列与现有广告系列具有相同的startDate和endDate,则查询也会有效。
测试表
tblCampaigns
campId campName startDate endDate status
1 Campaign1 2016-03-10 00:00:00 2016-03-17 00:00:00 active
2 Campaign2 2016-03-11 00:00:00 2016-03-18 00:00:00 active
3 Campaign3 2016-02-11 00:00:00 2016-02-18 00:00:00 closed
4 Campaign4 2016-04-11 00:00:00 2016-04-18 00:00:00 active
tblServices
serviceId serviceName
1 Car Washing
2 Car Painting
3 Car Maintenance
4 Brake Replacement
5 Gear Replacement
tblCampaignServices
id campId serviceId
1 1 1
2 1 2
3 3 1
4 3 2
5 3 3
6 2 4
7 4 3
使用此测试表,查询结果为:
serviceId serviceName
3 Car Maintenance
5 Gear Replacement
满足所有要求。
此致