适用于Microsoft Access 2013的SQL

时间:2019-01-24 21:31:59

标签: sql ms-access-2013

我正在设法计算返回服务的客户数量,其中要考虑到服务之前的评估得分的比较(按服务类型分组)。 (最终,我还希望能够忽略原始服务后一个月内的退货,但我很确定自己可以自己整理好皱纹)

在计算特定服务的结果时,它应查看任何服务类型的收益,而不仅仅是原始服务类型。 (编辑:*它还应该查看所有将来的回报,而不仅仅是下一个或最近的*)。

它不需要经常运行,但是由于动力不足的机器(这是一个非营利组织),有15000多个数据行和计算资源受到限制,因此效率会很好,但并不是绝对需要的。

样本数据

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

结果应为(不考虑日期填充选项):

Service1
  ReturnedWorse 0
  ReturnedSame  2
  ReturnedBetter 1

Service2
  ReturnedWorse 1
  ReturnedSame 0
  ReturnedBetter 1

Service3
  ReturnedWorse 2

到目前为止,我已经尝试过创建make table查询,然后可以查询这些查询以获取汇总信息,但是我有点卡住了,怀疑可能会有更好的方法。

我尝试过的事情:

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))));

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

使用窗口功能更容易做到这一点,但是在ms-access中不可用。

这是一个查询,可以解决我对您问题的理解:

  • t0:在表格中选择一条记录(购买服务的客户)
  • t1:同一客户使用INNER JOIN和相关子查询签定任何服务时,提取与 next 相对应的记录(如果没有这样的记录,初始记录未考虑在内)
  • 将上一个记录的得分与当前记录的得分进行比较
  • 按服务ID将结果分组

您可以在this db fiddlde中看到它的运行情况。结果与您的预期稍有不同(请参阅我的评论)...但是它们与上述解释一致;您可能希望使用相同的原理来调整一些规则以匹配您的确切预期结果。

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              |


根据您的评论,我了解到您希望考虑所有的未来回报,而不仅仅是下一个。这消除了对relatedead子查询的需要,并且实际上产生了预期的输出。参见this db fiddle

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              |