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 |
我正在尝试计算 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 |