SQL 用于 Microsoft Access 2013

SQL for Microsoft Access 2013

我正在尝试计算 return 需要额外服务的客户数量,这些服务考虑了服务之前评估分数的比较,按服务类型分组。 (最终,我还希望能够忽略原始服务一个月内的 returns,但我很确定我可以自己解决这些问题)

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

不需要经常运行,但是有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))));

如有任何帮助,我们将不胜感激。

如果使用 window 函数,这样做会更容易,但它们在 ms-access 中不可用。

这是一个解决我对你问题的理解的查询:

  • t0:在table中选择一条记录(客户购买服务)
  • t1 : 拉出对应于 下一次 同一客户使用 INNER JOIN 和相关子查询(如果有没有这样的记录,不考虑初始记录)
  • 将上一条记录的分数与当前记录进行比较
  • 按服务 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              |


根据您的评论,我了解到您想考虑 所有 未来 returns 而不仅仅是下一个。这消除了对 correlatead 子查询的需要,并且实际上产生了您预期的输出。见 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              |