[英]SQL for Microsoft Access 2013
I am trying to get a count of customers who return for additional services that takes into account a comparison of assessment scores prior to the service, grouped by the type of Service. 我正在尝试计算返回其他服务的客户,这些服务考虑了服务之前评估分数的比较,并按服务类型分组。 (Ultimately, I also want to be able to ignore returns that are within a month of the orginal service, but I'm pretty sure I can get that wrinkle sorted myself) (最终,我也希望能够忽略原始服务一个月内的回报,但我很确定我可以自己解决皱纹)
When counting results for a particular service, it should look at returns to any service type, not just the original service type. 在计算特定服务的结果时,它应该查看任何服务类型的返回,而不仅仅是原始服务类型。 (Edit: *It should also look at all future returns, not just the next or the most recent *). (编辑:*它还应该查看所有未来的回报,而不仅仅是下一个或最近的回报*)。
It does not need to be run often, but there are 15000+ lines of data and computational resources are limited by an underpowered machine (this is for a nonprofit organization), so efficiency would be nice but not absolutely needed. 它不需要经常运行,但是有15000多行数据和计算资源受到动力不足的机器的限制(这适用于非营利组织),因此效率很高但不是绝对需要。
Sample Data 样本数据
ServiceTable
CustomerID Service Date ScoreBefore
A Service1 1/1/2017 1
A Service2 1/3/2017 1
A Service1 1/1/2018 4
B Service3 3/1/2018 3
B Service1 6/1/2018 1
B Service1 6/2/2018 1
C Service2 1/1/2019 4
C Service2 6/1/2019 1
Results should be (not taking into account the date padding option): 结果应该是(不考虑日期填充选项):
Service1
ReturnedWorse 0
ReturnedSame 2
ReturnedBetter 1
Service2
ReturnedWorse 1
ReturnedSame 0
ReturnedBetter 1
Service3
ReturnedWorse 2
So far, I have tried creating make table queries that could then be queried to get the aggregate info, but I am a bit stuck and suspect there may be a better route. 到目前为止,我已经尝试创建make表查询,然后可以查询以获取聚合信息,但我有点卡住并怀疑可能有更好的路由。
What I have tried: 我尝试过的:
SELECT CustomerID, Service, Date, ScoreBefore INTO ReturnedWorse
FROM ServiceTable AS FirstStay
WHERE ((((SELECT COUNT(*)
FROM ServiceTable AS SecondStay
WHERE FirstStay.CustomerID=SecondStay.CustomerID
AND
FirstStay.ScoreBefore> SecondStay.ScoreBefore
AND
SecondStay.Date > FirstStay.Date))));
Any help would be greatly appreciated. 任何帮助将不胜感激。
This would have been easier to do with window functions, but they are not available in ms-access. 这对窗口函数来说更容易,但在ms-access中不可用。
Here is a query that solves my understanding of your question : 这是一个查询,解决了我对您的问题的理解:
t0
: pick a record in the table (a customer buying a service) t0
:选择表中的记录(购买服务的客户) t1
: pull out the record corresponding to the next time the same customer contracted any service with an INNER JOIN
and a correlated subquery (if there is no such record, the initial record is not taken into account) t1
:拉出对应下次同一客户与INNER JOIN
和相关子查询签订任何服务的对应的记录(如果没有这样的记录,则不考虑初始记录) You can see it in action in this db fiddlde . 您可以在此db fiddlde中看到它的运行情况 。 The results are slightly different from your expectation (see my comments)... but they are consistent with the above explanation ; 结果与您的期望略有不同(请参阅我的评论)......但它们与上述说明一致; you might want to adapt some of the rules to match your exact expected result, using the same principles. 您可能希望使用相同的原则调整某些规则以匹配您的确切预期结果。
SELECT
t0.service,
SUM(CASE WHEN t1.scorebefore < t0.scorebefore THEN 1 ELSE 0 END) AS ReturnedWorse,
SUM(CASE WHEN t1.scorebefore = t0.scorebefore THEN 1 ELSE 0 END) AS ReturnedSame,
SUM(CASE WHEN t1.scorebefore > t0.scorebefore THEN 1 ELSE 0 END) AS ReturnedBetter
FROM
mytable t0
INNER JOIN mytable t1
ON t0.customerid = t1.customerid
AND t0.date < t1.date
AND NOT EXISTS (
SELECT 1
from mytable
WHERE
customerid = t1.customerid
AND date < t1.date
AND date > t0.date
)
GROUP BY t0.service
| service | ReturnedWorse | ReturnedSame | ReturnedBetter | | -------- | ------------- | ------------ | -------------- | | Service1 | 0 | 2 | 0 | | Service2 | 1 | 0 | 1 | | Service3 | 1 | 0 | 0 |
From your comments, I understand that you want to take into account all future returns and not only the next one. 根据您的评论,我了解您希望考虑所有未来的回报,而不仅仅是下一个回报。 This eliminates the need for a correlatead subquery, and actually yields your expected output. 这消除了对correlatead子查询的需要,并实际产生了您的预期输出。 See this db fiddle : 看到这个db小提琴 :
SELECT
t0.service,
SUM(CASE WHEN t1.scorebefore < t0.scorebefore THEN 1 ELSE 0 END) AS ReturnedWorse,
SUM(CASE WHEN t1.scorebefore = t0.scorebefore THEN 1 ELSE 0 END) AS ReturnedSame,
SUM(CASE WHEN t1.scorebefore > t0.scorebefore THEN 1 ELSE 0 END) AS ReturnedBetter
FROM
mytable t0
INNER JOIN mytable t1
ON t0.customerid = t1.customerid
-- AND t0.service = t1.service
AND t0.date < t1.date
GROUP BY t0.service
| service | ReturnedWorse | ReturnedSame | ReturnedBetter | | -------- | ------------- | ------------ | -------------- | | Service1 | 0 | 2 | 1 | | Service2 | 1 | 0 | 1 | | Service3 | 2 | 0 | 0 |
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.