Рассчитать среднюю разницу в дате - PullRequest
0 голосов
/ 29 марта 2019

Это основная настройка таблицы (присутствует только DDL для соответствующих столбцов).MySQL версия 8.0.15

Намерение - показать среднее значение интервала разницы в датах между заказами.

    CREATE TABLE final (
    prim_id INT(11) NOT NULL AUTO_INCREMENT,
    order_ID INT(11) NOT NULL,
    cust_ID VARCHAR(45) NOT NULL,
    created_at DATETIME NOT NULL,
    item_name VARCHAR(255) NOT NULL,
    cust_name VARCHAR(255) NOT NULL,
    PRIMARY KEY (prim_id),
    COLLATE='latin1_swedish_ci'
    ENGINE=InnoDB
    AUTO_INCREMENT=145699

Дополнительная информация:

cust ID -> cust_name (one-to-many)
cust_ID -> order_ID (one-to-many)
order ID -> item_name (one-to-many)
order ID -> created_at (one-to-one)
prim_id -> *everything* (one-to-many)

Я думалиспользования min (созданный_ат) и максимальный (созданный_ат), но это исключит все порядки между самым старым и самым новым.Мне нужно более утонченное решение.

Конечный результат должен выглядеть следующим образом:

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

1 Ответ

1 голос
/ 29 марта 2019

Если я правильно понял, вы можете использовать подзапрос, получая дату предыдущего заказа.Используйте datediff() для получения разницы между датами и avg() для получения среднего значения этих различий.

SELECT f1.cust_id,
       avg(datediff(f1.created_at,
                    (SELECT f2.created_at
                            FROM final f2
                            WHERE f2.cust_id = f1.cust_id
                                  AND (f2.created_at < f1.created_at
                                        OR f2.created_at = f1.created_at
                                           AND f2.order_id < f1.order_id)
                            ORDER BY f2.created_at DESC,
                                     f2.order_id DESC
                            LIMIT 1)))
       FROM final f1
       GROUP BY f1.cust_id;

Правка:

Если может быть больше строк дляодин идентификатор заказа, как упоминалось в программном обеспечении KIKO, нам нужно сделать SELECT из отдельного набора заказов, например:

SELECT f1.cust_id,
       avg(datediff(f1.created_at,
                    (SELECT f2.created_at
                            FROM (SELECT DISTINCT f3.cust_id,
                                                  f3.created_at,
                                                  f3.order_id
                                         FROM final f3) f2
                            WHERE f2.cust_id = f1.cust_id
                                  AND (f2.created_at < f1.created_at
                                        OR f2.created_at = f1.created_at
                                           AND f2.order_id < f1.order_id)
                            ORDER BY f2.created_at DESC,
                                     f2.order_id DESC
                            LIMIT 1)))
       FROM (SELECT DISTINCT f3.cust_id,
                             f3.created_at,
                             f3.order_id
                    FROM final f3) f1
       GROUP BY f1.cust_id;

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


2-е редактирование:

Или, альтернативно, получение максимальной отметки времени создания для заказа, если они могут отличаться:

SELECT f1.cust_id,
       avg(datediff(f1.created_at,
                    (SELECT f2.created_at
                            FROM (SELECT max(f3.cust_id) cust_id,
                                         max(f3.created_at) created_at,
                                         f3.order_id
                                         FROM final f3
                                         GROUP BY f3.order_id) f2
                            WHERE f2.cust_id = f1.cust_id
                                  AND (f2.created_at < f1.created_at
                                        OR f2.created_at = f1.created_at
                                           AND f2.order_id < f1.order_id)
                            ORDER BY f2.created_at DESC,
                                     f2.order_id DESC
                            LIMIT 1)))
       FROM (SELECT max(f3.cust_id) cust_id,
                    max(f3.created_at) created_at,
                    f3.order_id
                    FROM final f3
                    GROUP BY f3.order_id) f1
       GROUP BY f1.cust_id;
...