Лучший способ в MySQL или направляющих для получения AVG в день в определенном диапазоне дат

ProductDao - это не боб .. Вот почему. Репозиторий, контроллер, сервис - все это типа bean-компонента. Убедитесь, что это какой боб ..... Спасибо.

5
задан Jonathan Leffler 8 January 2009 в 06:15
поделиться

4 ответа

Существует ли причина (кроме даты один уже упомянутый), почему Вы не использовали бы встроенные возможности функции группы в ActiveRecord? Вы, кажется, обеспокоены "последующей обработкой", которая я не думаю, действительно что-то для волнения о.

Вы находитесь в направляющих, таким образом, необходимо, вероятно, искать решение для направляющих сначала [1]. Моя первая мысль состояла бы в том, чтобы сделать что-то как

Product.average(:sales_price, :group => "DATE(created_at)", :conditions => ["merchant_id=?", 1])

который ActiveRecord, в который превращаются в значительной степени SQL, Вы описали. Принятие там является заявленным has_many ассоциация между Продавцом и продуктом, затем Вы, вероятно, лучше использовали бы это, таким образом, что-то как:

ave_prices = Merchant.find(1).products.average(:sales_price, :group => "DATE(created_at)")

(Я надеюсь, что Ваше описание модели как "products_sold" является некоторой ошибкой записи, btw - в противном случае Вы несколько вне сообщения со своим именованием класса!)

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

Я предположу, что Вы знаете свой диапазон дат, скажем, он определяется как все даты от from_date кому: to_date.

date_aves = (from_date..to_date).map{|dt| [dt, 0]}

Это создает полный список дат как массив. Нам не нужны даты, где мы получили среднее число:

ave_price_dates = ave_prices.collect{|ave_price| ave_price[0]} # build an array of dates
date_aves.delete_if { |dt| ave_price.dates.index(dt[0]) } # remove zero entries for dates retrieved from DB
date_aves.concat(ave_prices)     # add the query results
date_aves.sort_by{|ave| ave[0] } # sort by date

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


[1] Я не говорю, не используют SQL - ситуации происходят, где ActiveRecord не может генерировать самый эффективный запрос, и Вы возвращаетесь find_by_sql. Это прекрасно, это, как предполагается, похоже на это, но я думаю, что необходимо попытаться использовать его только как последнее прибежище.

7
ответ дан 13 December 2019 в 19:37
поделиться

Для любого такого запроса необходимо будет найти, что механизм генерирует таблицу с одной строкой для каждой даты, относительно которой Вы хотите сообщить. Затем Вы сделаете внешнее объединение той таблицы с таблицей данных, которую Вы анализируете. Вам, вероятно, также придется играть с NVL или ОБЪЕДИНИТЬ для преобразования, аннулирует в, обнуляет.

Твердая часть разрабатывает, как генерировать (временную) таблицу, которая содержит список дат диапазона, который необходимо проанализировать. Это является определенным для DBMS.

Ваша идея отобразить дату/временные стоимости на единственную дату является пятном на, все же. Необходимо было бы вытянуть подобный прием - отображающий все даты на формат даты ISO 8601 как 2009-W01 в течение недели 01 - если бы Вы хотели проанализировать еженедельные продажи.

Кроме того, Вы добились бы большего успеха для отображения Формата даты на 08.01.2009 нотаций, потому что затем можно отсортировать в хронологическом порядке использование простого символьного вида.

2
ответ дан 13 December 2019 в 19:37
поделиться

MySQL имеет возвращающие набор функции? Т.е. функции, которые возвращают различные значения на каждой строке запроса? Как пример от PostgreSQL, можно сделать:

select 'foo', generate_series(3, 5);

Это произведет набор результатов, состоящий из 2 столбцов и 3 строки, где левый столбец содержит 'нечто' на каждой строке, и правый столбец содержит 3, 4 и 5.

Так, принятие Вас имеет эквивалент generate_series() в MySQL и подзапросах: То, в чем Вы нуждаетесь, является a LEFT OUTER JOIN от этой функции до запроса, который Вы уже имеете. Это гарантирует, чтобы Вы видели, что каждая дата появляется в выводе:

SELECT
    avg(sales_price) as avg,
    DATE_FORMAT(the_date, '%m-%d-%Y') as date
FROM (select cast('2008-JAN-01' as date) + generate_series(0, 364) as the_date) date_range
LEFT OUTER JOIN products_sold on (the_date = created_at)
WHERE merchant_id = 1
GROUP BY date;

Вы, возможно, должны играть с этим немного для разбираний в синтаксисе для MySQL.

0
ответ дан 13 December 2019 в 19:37
поделиться

Чтобы немного высохнуть:

ave_prices = Merchant.find(1).products.average(:sales_price, :group => "DATE(created_at)")
date_aves = (from_date..to_date).map{|dt| [dt, ave_prices[dt.strftime "%Y-%m-%d"] || 0]}
2
ответ дан 13 December 2019 в 19:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: