2012-02-29 2 views
3

В моей таблице MySQL есть следующие столбцы: datetime, price_paid. Я пытаюсь рассчитать средние продажи в день недели, между 2 датами. Это означает, что мне нужно выбрать сумму продаж, между датами startDate и endDate, сгруппированными по будням и разделить их на количество раз, каждый раз в будние дни происходит в этом диапазоне.Расчет среднесуточного (или: сколько понедельников находится в диапазоне дат?)

Я получил первую часть:

SELECT DATE_FORMAT(datetime, '%a') AS field1, 
round(SUM(price_paid)/ THEVALUEIMLOOKINGFOR) AS field2 
FROM Bills 
WHERE date(datetime) BETWEEN '2012-01-02' AND '2012-01-09' 
GROUP BY weekday(datetime) 

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

Может кто-нибудь помочь мне заполнить мою инструкцию SQL?

Спасибо за ваше время!

+0

Итак, вы в конечном итоге хотите увидеть что-то вроде среднесуточных: Пн, Вт, Ср, и т.д ... в течение диапазона дат?Если это так, у некоторых диапазонов может быть только 2 ср. Против 3 пн и тью (или других подобных) ... – DRapp

+0

Правильно - мне нужно среднесуточное. Надеюсь, что нижеприведенное решение учитывает это. –

ответ

6

Возможно, я слишком упрощен, но учитывая, что вы уже группируетесь по будням, не просто подсчитайте (*) вычислить номер данного дня недели в этом диапазоне за каждый будний день?

так:

SELECT DATE_FORMAT(datetime, '%a') AS field1, 
round(SUM(price_paid)/ COUNT(DISTINCT(date(datetime)))) AS field2 
FROM Bills 
WHERE date(datetime) BETWEEN '2012-01-02' AND '2012-01-09' 
GROUP BY weekday(datetime) 

отредактированные так не завышению несколько раз в тот же день (спасибо DRapp)

+3

Я думаю, что вы ОЧЕНЬ близко ... однако, если бы у них было несколько счетов в ту же дату, вы бы посчитали делитель. COUNT (DISTINCT) на отформатированном yyyy-mm-dd поможет обеспечить, чтобы ... – DRapp

+1

так что 'COUNT (DISTINCT (date (datetime))' – msonsona

+0

Спасибо за ответ. Один вопрос: рассмотрим случай, когда диапазон дат составляет 8 дней (т. е. есть 2 понедельника, скажем), и поэтому вам нужно разделить покупку 2 понедельника? Будет ли еще необходимо? –

0

Вот хранимая функция называется MakeDateList:

DELIMITER $$ 
DROP FUNCTION IF EXISTS `junk`.`MakeDateList` $$ 

CREATE FUNCTION `junk`.`MakeDateList` 
(
    BeginDate DATE, 
    EndDate DATE, 
    InclusionList VARCHAR(20) 
) 

RETURNS VARCHAR(4096) 
DETERMINISTIC 
BEGIN 
    DECLARE RunningDate DATE; 
    DECLARE rv VARCHAR(4096); 
    DECLARE comma CHAR(1); 
    DECLARE IncList,DOWValue VARCHAR(20); 
    DECLARE OK_To_Add INT; 

    SET IncList = CONCAT(',',InclusionList,','); 
    SET comma = ''; 
    SET rv = ''; 
    SET RunningDate = BeginDate; 

    WHILE RunningDate <= EndDate DO 
    SET OK_To_Add = 0; 
    SET DOWValue = CONCAT(',',DAYOFWEEK(RunningDate),','); 
    IF LOCATE(DOWValue,IncList) > 0 THEN 
     SET OK_To_Add = 1; 
    END IF; 
    IF OK_To_Add = 1 THEN 
     SET rv = CONCAT(rv,comma,RunningDate); 
    END IF; 
    SET comma = ','; 
    SET RunningDate = RunningDate + INTERVAL 1 DAY; 
    END WHILE; 
RETURN rv; 
END $$ 
DELIMITER ; 

Он имеет три параметра: BeginDate, EndDate и InclusionList

InclusionList - это запятая speararted список номеров (действительные числа 1-7)

1 = Sunday 
2 = Monday 
3 = Tuesday 
4 = Wednesday 
5 = Thursday 
6 = Friday 
7 = Saturday 

Таким образом, чтобы понедельники, сделать InclusionList 2

Пример: Вызов MakeDateList ('2011-10-01', '2011-10-01 ',' 2 ') должен дать вам понедельники за весь октябрь 2011 года

0

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

Я изменил запрос на включение внешнего запроса, который возвращает общее число средних значений. Однако теперь field1 не имеет смысла, так как больше она может быть любой из дат в зависимости от того, какой вариант заказа вы используете

SELECT field1, SUM (field2) FROM (
    SELECT DATE_FORMAT(datetime, '%a') AS field1, 
    AVG(price_paid) AS field2 
    FROM Bills 
    WHERE date(datetime) BETWEEN '2012-01-02' AND '2012-01-09' 
    GROUP BY weekday(datetime) 
) 
+1

Пробовал это. средний за _a_ день, а не общее число средних. –

2

Я знаю, что это старый, но «похоже на работу». не совсем достаточно. Фактически, он будет подсчитывать количество понедельников, если бы был день с транзакциями ZERO.

Существует формула для подсчета дней недели в диапазоне дат. Вам нужно начать с известного дня недели. «1970-01-05» был ПОНЕДЕЛЬНИК.

Вот функция, которую вы можете использовать:

create function CountDaysOfWeek(
    DateFrom DATETIME, 
    DateTo DATETIME, 
    DayOfWeek int 
) 
RETURNS int 
return FLOOR(DATEDIFF(DateTo,'1970-01-03' + INTERVAL DayOfWeek DAY)/7) - 
    FLOOR(DATEDIFF(DateFrom,'1970-01-03' + INTERVAL (DayOfWeek+1) DAY)/7); 
Смежные вопросы