В Lisp есть списки, например: (mary выбрасывает мяч).
В некоторых списках описывается вычисление, например: (* pi (+ rr))
а второй - выражение, подходящее для того, чтобы оценщик мог пережевывать.
Но нам нужен способ включения данных в выражения. Итак, несколько десятилетий назад был введен специальный оператор, который позволил бы это сделать, например: (count-существительные (цитата (mary бросила мяч)))
Прошло время, и разработчикам надоело писать (цитата ... ), поэтому они изобрели короткую нотную запись: (count-существительные (mary бросили мяч)).
В эти дни стенография выполняется во время чтения, так как символы считываются из файла или от терминала. Это делается с помощью средства, известного как «считывающие макросы». Это имя сбивает с толку большинство новичков, поскольку на языке, называемом «макросы», есть еще одно средство, которое действительно имеет мало общего с чтением файлов. Они обычно используются для добавления небольшого синтаксического сахара. Как в этом примере цитаты. После того, как поток файлов (или терминалов) был прочитан, все это всего лишь список.
Вы заметите, что если вы введете: (quote bob) в свой запрос lisp, вы вернетесь: 'bob. Принтер хорошо осведомлен о соглашении, которое (quote bob) имеет сокращенную форму. Если вы когда-нибудь решите написать свои собственные макросы читателей, вы можете научить принтер, как играть.
Макросы, как v.s. читайте макросы, позвольте вам представить свои собственные специальные операторы. И это позволяет вам встраивать пользовательские языки, специфичные для домена, в ваш код. Итак - вид макроса позволяет расширять семантику и макросы чтения, чтобы вы могли расширить синтаксис. Макросы влияют на поведение компилятора и оценщика.
Это зависит от вашего бэкэнда, но вы хотите разделить сумму суммы на разницу в днях между вашей максимальной и минимальной отметкой времени. В Postgres вы можете просто вычесть две даты, чтобы получить количество дней между ними. В MySQL есть функция DateDiff, которая принимает две даты и возвращает количество дней между ними.
class Date(Func):
function = 'DATE'
class MySQLDateDiff(Func):
function = 'DATEDIFF'
def __init__(self, *expressions, **extra):
expressions = [Date(exp) for exp in expressions]
extra['output_field'] = extra.get('output_field', IntegerField())
super().__init__(*expressions, **extra)
class PgDateDiff(Func):
template = "%(expressions)s"
arg_joiner = ' - '
def __init__(self, *expressions, **extra):
expressions = [Date(exp) for exp in expressions]
extra['output_field'] = extra.get('output_field', IntegerField())
super().__init__(*expressions, **extra)
agg = {
avg_spend: ExpressionWrapper(
Sum('amount') / (PgDateDiff(Max('timestamp'), Min('timestamp')) + Value(1)),
output_field=DecimalField())
}
avg_spend = Payment.objects.aggregate(**agg)
Это выглядит примерно правильно для меня, конечно, я не проверял это. Конечно, используйте MySQLDateDiff, если это ваш бэкэнд.
Вы можете агрегировать минимальную и максимальную временную отметку и сумму суммы:
from django.db.models import Min, Max, Sum
def average_spending_per_day():
aggregate = Payment.objects.aggregate(Min('timestamp'), Max('timestamp'), Sum('amount'))
min_datetime = aggregate.get('timestamp__min')
if min_datetime is not None:
min_date = min_datetime.date()
max_date = aggregate.get('timestamp__max').date()
total_amount = aggregate.get('amount__sum')
days = (max_date - min_date).days + 1
return total_amount / days
return 0
Если есть min_datetime
, то в таблице БД есть некоторые данные, а также есть максимальная дата и общее количество. сумма, в противном случае мы возвращаем 0 или что вы хотите.