SQL для Microsoft Access 2013 - PullRequest
       11

SQL для Microsoft Access 2013

0 голосов
/ 25 января 2019

Я пытаюсь получить количество клиентов, возвращающихся за дополнительными услугами, которое учитывает сравнение оценочных баллов до предоставления услуги, сгруппированных по типу услуги. (В конечном счете, я также хочу иметь возможность игнорировать возвраты, которые находятся в течение месяца после первоначального обслуживания, но я почти уверен, что смогу разобрать эту морщинку самостоятельно)

При подсчете результатов для конкретной службы следует учитывать возврат к любому типу службы, а не только к исходному типу службы. (Изменить: * Он также должен учитывать все будущие доходы, а не только следующий или самый последний *).

Его не нужно часто запускать, но существует более 15 000 строк данных, и вычислительные ресурсы ограничены недостаточно мощным компьютером (это для некоммерческой организации), поэтому эффективность была бы хорошей, но не абсолютно необходимой.

Пример данных

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 голосов
/ 25 января 2019

Это было бы проще сделать с оконными функциями, но они не доступны в ms-access.

Вот запрос, который решает мое понимание вашего вопроса:

  • t0: выбрать запись в таблице (клиент, покупающий услугу)
  • t1: извлечь запись, соответствующую в следующий раз, когда тот же клиент заключил контракт на любую услугу сINNER JOIN и коррелированный подзапрос (если такой записи нет, начальная запись не учитывается)
  • сравнивает оценку предыдущей записи с текущей
  • , группируетрезультаты по идентификатору службы

Вы можете увидеть его в действии в 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              |


Из ваших комментариев я понимаю, что вы хотите принять во внимание все будущее возвращается, а не только следующее.Это устраняет необходимость в коррелированном подзапросе и фактически дает ожидаемый результат.Смотрите эту дб скрипку :

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              |
...