Функция линейного уравнения с MySQL?

#mysql #math

#mysql — сервер #математика #mysql

Вопрос:

Я хочу вычислить оценки для некоторых данных, которые у меня есть в базе данных MySQL. Оценка будет вычислена следующим образом:

 score = COUNT(purchases MADE BETWEEN NOW() AND (NOW() - 1 WEEK))
    0.7 * COUNT(purchases MADE BETWEEN (NOW() - 1 WEEK) AND (NOW() - 2 WEEKS))
    0.4 * COUNT(purchases OLDER THAN (NOW() - 2 WEEKS))
  

У меня есть покупки в таблице со столбцом purchase_time.

Возможно ли сделать это в MySQL и получить вывод, подобный следующему?

 ORDER_ID    SCORE
   3          8
   4          3
   5          15
  

Спасибо

— РЕДАКТИРОВАТЬ — Структура таблицы является:

 tblOrder - table
id - primary key
created - time stamp
  

Комментарии:

1. можете ли вы указать структуру ваших таблиц и названия таблиц?

Ответ №1:

 SELECT  orderId,
        SUM
        (
        CASE
        WHEN purchase_date > NOW() - INTERVAL 1 WEEK AND purchase_date <= NOW() THEN
                1
        WHEN purchase_date > NOW() - INTERVAL 2 WEEK AND purchase_date <= NOW() - INTERVAL 1 WEEK THEN
                0.7
        ELSE
                0.3
        END
        )
FROM    mytable
GROUP BY
        orderId
  

Комментарии:

1. 1 ты был быстрее 🙂 Однако я предлагаю, чтобы мой вариант был более оптимизирован, поскольку вычисление случая выполняется только один раз (конечно, это очень незначительное улучшение для систем, связанных с вводом-выводом, поскольку это влияет только на загрузку процессора, да и то незначительным образом)

2. Ах, это работает, потому что не использует count, только SUM, был введен в заблуждение комментарием выше о count, но sum (1) — хорошая альтернатива для count clever.

Ответ №2:

Ваши значения между и старше должны быть преобразованы в РЕГИСТР.

 CASE case_value
    WHEN when_value THEN statement_list
    [WHEN when_value THEN statement_list] ...
    [ELSE statement_list]
END CASE
  

В то же время вы можете переписать выражение так, чтобы в конкретных случаях учитывались такие факторы, как

 SELECT SUM(
         CASE DATEDIFF(now(),purchase_datetime) DIV 7
           WHEN 0 THEN 1
           WHEN 1 THEN 0.7
           ELSE 0.4
         END
       )
FROM table
WHERE purchase_datetime < now()
GROUP BY ORDER_ID
  

Комментарии:

1. Это должно быть SUM , не COUNT

2. @Quassnoi — да, хорошее наблюдение. Я задавался вопросом, почему это не сработало. Спасибо @Unreason, это работает и проще, чем объединения :-).

Ответ №3:

 SELECT ORDER ID, COUNT(purchases MADE BETWEEN NOW() AND (NOW() - 1 WEEK))
  0.7 * COUNT(purchases MADE BETWEEN (NOW() - 1 WEEK) AND (NOW() - 2 WEEKS))
  0.4 * COUNT(purchases OLDER THAN (NOW() - 2 WEEKS)) AS SCORE
FROM TABLE
  

должно сработать, в настоящее время у меня не установлен mysql, поэтому я не могу его протестировать.

кроме того, используйте datediff, чтобы определить, находится ли дата между диапазоном дат

Комментарии:

1. нет, это не поможет, COUNT поддерживает только COUNT (выражение) и COUNT (ОТЛИЧНОЕ выражение), см. dev.mysql.com/doc/refman/5.1/en /…

Ответ №4:

 SELECT order_id, sum(score) FROM
( 
  (SELECT Order_id, COUNT(id) AS Score FROM purchases 
    WHERE purchase_time BETWEEN CURDATE() AND DATE_SUB(CURDATE(),INTERVAL 1 WEEK))
    GROUP BY order_id
  UNION ALL
    (SELECT Order_id, (COUNT(id) * 0.7) AS score FROM purchases
    WHERE purchase_time BETWEEN DATE_SUB(CURDATE(),INTERVAL 1 WEEK) 
                    AND DATE_SUB(CURDATE(),INTERVAL 2 WEEK))
    GROUP BY order_id 
  UNION ALL
    (SELECT Order_id, (COUNT(id) * 0.4) AS score FROM purchases
    WHERE purchase_time < DATE_SUB(CURDATE(),INTERVAL 2 WEEK)) 
    GROUP BY order_id
) s
GROUP BY order_id;
  

Комментарии:

1. Йохан, обычно это просто неправильный подход. Ни один планировщик запросов не увидит, что он может получить то, что вы просите за одно сканирование, и выполнит три запроса и объединит их. Итак, если в purchase_time нет индекса, у вас будет запрос, который в 3 раза медленнее, чем должен быть (и в три раза сложнее). Кроме того, вы округляете данные слишком рано (если округление вообще необходимо).

2. @Unisoron, объединение не очень, я согласен, хотелось бы увидеть решение без объединения, исправлено раннее округление.

3. спасибо за усилия. Я пробовал это, но не смог заставить это работать, а другие подходы выглядят более эффективными.

4. В ответах Quassnoi и моих не используется объединение. @Paul J, этот подход в конечном итоге сработал бы, просто не так эффективен.