简体   繁体   English

SQL for Microsoft Access 2013

[英]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和相关子查询签订任何服务的对应的记录(如果没有这样的记录,则不考虑初始记录)
  • compare the score of the previous record to the current one 比较前一记录的得分与当前记录的得分
  • group the results by service id 按服务ID对结果进行分组

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM