জ্যাঙ্গো: তারিখ অনুসারে গ্রুপ (দিন, মাস, বছর)


94

আমি এর মতো একটি সাধারণ মডেল পেয়েছি:

class Order(models.Model):
    created = model.DateTimeField(auto_now_add=True)
    total = models.IntegerField() # monetary value

এবং আমি এক মাস-পর-মাস এর বিচ্ছেদ আউটপুট করতে চাই:

  • এক মাসে সেখানে কতগুলি বিক্রয় হয়েছিল ( COUNT)
  • সম্মিলিত মান ( SUM)

আমি নিশ্চিত না যে এটি আক্রমণ করার সর্বোত্তম উপায় কী। আমি কিছুটা ভয়ঙ্কর-দেখার মতো অতিরিক্ত-বাছাই করা প্রশ্নগুলি দেখেছি তবে আমার সাধারণ মনটি আমাকে বলছে যে আমি কেবল সংখ্যা পুনরাবৃত্তির চেয়ে ভাল হতে পারি, একটি স্বেচ্ছাসেবী শুরুর বছর / মাস থেকে শুরু করে এবং চলতি মাসে পৌঁছা পর্যন্ত গণনা অবধি সহজ করে ফেলেছি এই মাসের জন্য ক্যোয়ারী ফিল্টারিং। আরও ডেটাবেস কাজ - বিকাশকারী কম চাপ!

আপনি সবচেয়ে সার্থক করে তোলে? আমি কি একটি দ্রুত উপায় তথ্য দ্রুত টেবিল ফিরে টানতে পারেন? বা আমার নোংরা পদ্ধতি সম্ভবত সেরা ধারণা?

আমি জাজানো 1.3 ব্যবহার করছি। নিশ্চিত না যে তারা GROUP_BYসম্প্রতি কোনও সুন্দর উপায় যুক্ত করেছে কিনা ।


উত্তর:


225

জাজানো 1.10 এবং তারপরে

জ্যাঙ্গো ডকুমেন্টেশন তালিকা extraযেমন শীঘ্রই অননুমোদিত । (এটি চিহ্নিত @ নাম, @ লাকাস ০৩-কে নির্দেশ করার জন্য ধন্যবাদ) আমি একটি টিকিট খুলেছি এবং এটিই সমাধানটি জার্সওয়াহ সরবরাহ করেছে।

from django.db.models.functions import TruncMonth
from django.db.models import Count

Sales.objects
    .annotate(month=TruncMonth('timestamp'))  # Truncate to month and add to select list
    .values('month')                          # Group By month
    .annotate(c=Count('id'))                  # Select the count of the grouping
    .values('month', 'c')                     # (might be redundant, haven't tested) select month and count 

পুরানো সংস্করণ

from django.db import connection
from django.db.models import Sum, Count

truncate_date = connection.ops.date_trunc_sql('month', 'created')
qs = Order.objects.extra({'month':truncate_date})
report = qs.values('month').annotate(Sum('total'), Count('pk')).order_by('month')

সম্পাদনা

  • যুক্ত গণনা
  • Django> = 1.10 এর জন্য যুক্ত করা তথ্য

4
আপনি কী ডেটাবেস ব্যাকএন্ড ব্যবহার করছেন - এটি >>> qs.extra({'month':td}).values('month').annotate(Sum('total')) [{'total__sum': Decimal('1234.56'), 'month': datetime.datetime(2011, 12, 1, 0, 0)}]
পোস্টগ্রিতে দুর্দান্ত

4
@ এসডনাম ফিক্সড (জর্শওয়াহকে ধন্যবাদ)

4
ট্র্যাঙ্কমনথ জ্যাঙ্গো 1.8 তে উপলব্ধ নয়
সুধাকরণ প্যাকিয়ানাথন

4
ধন্যবাদ, দুর্দান্ত কাজ করে প্রাক-1.10 সংস্করণের জন্য কর্নার কেস: যদি একই মডেল (যেমন: টাইমস্ট্যাম্প) থাকতে পারে এমন অন্যান্য মডেলগুলিতে যদি কোনও একজন / ফিল্টারগুলিতে যোগদান করে তবে অবশ্যই ক্ষেত্রটি পুরোপুরি যোগ্যতা অর্জন করতে হবে -'{}.timestamp'.format(model._meta.db_table)
zsepi

4
কেবলমাত্র একটি দ্রষ্টব্য নোট যে জ্যাঙ্গো USE_TZসেটিংটি থাকলে Trueদুটি সংস্করণ হুবহু সমান নয়। ব্যবহার করা সংস্করণটি ট্রান্সকাটিংয়ের আগে সেটিংস TruncMonthদ্বারা নির্দিষ্ট টাইম জোনে টাইমস্ট্যাম্পকে রূপান্তরিত করবে TIME_ZONE, যখন ব্যবহার করা সংস্করণটি date_trunc_sqlডাটাবেসে কাঁচা ইউটিসি টাইমস্ট্যাম্পকে ছাঁটাই করবে।
ড্যানিয়েল হার্ডিং

36

@ প্রতিক্রিয়া জবাবের জন্য কেবল একটি সামান্য সংযোজন: এটি আমার পক্ষে জ্যাঙ্গো 1.10.6 এবং পোস্টগ্রিসের সাথে কাজ করে না। আমি এটি সংশোধন করতে শেষে অর্ডার_বাই () যুক্ত করেছি।

from django.db.models.functions import TruncMonth
Sales.objects
    .annotate(month=TruncMonth('timestamp'))  # Truncate to month and add to select list
    .values('month')                          # Group By month
    .annotate(c=Count('id'))                  # Select the count of the grouping
    .order_by()

4
হ্যাঁ: ডকস.ডজ্যাঙ্গোপ্রজেক্ট.এইন / ১.১১ / টপিক্স / ডিবি / অ্যাগগ্রিগেশন/ … ... ভাল ডিজাইনের মতো মনে হয় না তবে তারা j জাঙ্গো ছেলেরা খুব স্মার্ট, তাই এটি আসলে।
উইলিয়ামস

TruncDateআপনাকে তারিখ অনুসারে (মাসের দিন) দলবদ্ধ করতে দেয়
নিল

11

আরেকটি পন্থা ব্যবহার করা হয় ExtractMonth। আমি কেবলমাত্র এক তারিখের সময়কালের মূল্য ফেরত দেওয়ার কারণে ট্রাঙ্কমন্ট ব্যবহার করে সমস্যায় পড়েছি। উদাহরণস্বরূপ, ২০০৯ সালে কেবল মাসগুলিই ফেরত আসছিল। ExtractMonth এই সমস্যাটিকে নিখুঁতভাবে সমাধান করেছে এবং নীচের মত ব্যবহার করা যেতে পারে:

from django.db.models.functions import ExtractMonth
Sales.objects
    .annotate(month=ExtractMonth('timestamp')) 
    .values('month')                          
    .annotate(count=Count('id'))                  
    .values('month', 'count')  

2
    metrics = {
        'sales_sum': Sum('total'),
    }
    queryset = Order.objects.values('created__month')
                               .annotate(**metrics)
                               .order_by('created__month')

querysetঅর্ডার অফ একটি তালিকা, প্রতি মাসে এক লাইন, বিক্রয় এর সমষ্টি মিশ্রন হল:sales_sum

@ জাজানো ২.১..7


1

এখানে আমার নোংরা পদ্ধতি। এটি নোংরা.

import datetime, decimal
from django.db.models import Count, Sum
from account.models import Order
d = []

# arbitrary starting dates
year = 2011
month = 12

cyear = datetime.date.today().year
cmonth = datetime.date.today().month

while year <= cyear:
    while (year < cyear and month <= 12) or (year == cyear and month <= cmonth):
        sales = Order.objects.filter(created__year=year, created__month=month).aggregate(Count('total'), Sum('total'))
        d.append({
            'year': year,
            'month': month,
            'sales': sales['total__count'] or 0,
            'value': decimal.Decimal(sales['total__sum'] or 0),
        })
        month += 1
    month = 1
    year += 1

কয়েক বছর / মাস লুপিংয়ের আরও ভাল উপায় হতে পারে তবে আমি যা যত্ন করি তা সত্যিই নয় :)


বিটিডব্লিউ এটি দুর্দান্ত কাজ করবে তবে আপনি জানেন কয়েক মাস ধরে লুপও দুর্দান্ত ধারণা নয়। যদি কেউ কোনও মাসের দিনে এটি তৈরি করতে চায় তবে এই লুপটি 30-31 দিন দ্বারা পুনরাবৃত্তি হবে। অন্যথায় এটি
ঠিকঠাক

আপনার লক্ষ লক্ষ রেকর্ড থাকলে এটি খুব ধীর
20:25

নিখুঁতভাবে! প্রশ্ন পোস্ট করার সময় আমার সমাধান কী ছিল তা দেখানোর জন্য আমি এটি যুক্ত করেছি। অন্য উত্তরগুলি আরও ভাল।
অলি

0

আপনি এখানে সময় স্বেচ্ছাসেবী সময় দ্বারা ডেটা গ্রুপ করতে পারেন কিভাবে:

from django.db.models import F, Sum
from django.db.models.functions import Extract, Cast
period_length = 60*15 # 15 minutes

# Annotate each order with a "period"
qs = Order.objects.annotate(
    timestamp=Cast(Extract('date', 'epoch'), models.IntegerField()),
    period=(F('timestamp') / period_length) * period_length,
)

# Group orders by period & calculate sum of totals for each period
qs.values('period').annotate(total=Sum(field))

0

আমার ডাটাবেসে অর্ডার টেবিল রয়েছে। আমি গত 3 মাসে প্রতি মাসে অর্ডার গণনা করতে যাচ্ছি

from itertools import groupby
from dateutil.relativedelta import relativedelta

date_range = datetime.now()-relativedelta(months=3)
aggs =Orders.objects.filter(created_at=date_range)\
            .extra({'date_created':"date(created_at)"}).values('date_created')

for key , group in groupby(aggs):
     print(key,len(list(group)))

তৈরি_এটি তারিখের ক্ষেত্র। অতিরিক্ত ফাংশন দ্বারা যা করা হয়েছে তা তারিখের মানগুলি থেকে তারিখ গ্রহণ করে। ডেটটাইম ব্যবহার করার সময় আমরা গণনা সঠিক নাও পেতে পারি কারণ একদিনে বিভিন্ন সময়ে অবজেক্ট তৈরি করা হয়।

ফর লুপটি তারিখ এবং গণনার সংখ্যা মুদ্রণ করবে


-1

মাসে:

 Order.objects.filter().extra({'month':"Extract(month from created)"}).values_list('month').annotate(Count('id'))

বছর অনুসারে:

 Order.objects.filter().extra({'year':"Extract(year from created)"}).values_list('year').annotate(Count('id'))

দিনের মধ্যে:

 Order.objects.filter().extra({'day':"Extract(day from created)"}).values_list('day').annotate(Count('id'))

গণনা আমদানি করতে ভুলবেন না

from django.db.models import Count

জ্যাঙ্গোর জন্য <1.10


4
হ্যাঁ, দুর্দান্ত অনুশীলন, মডেলগুলি থেকে সমস্ত আমদানি করুন
জেসি রোকামন্ডে

আমি স্পষ্টভাবে বিদ্রূপ ছিল। এটি করা একটি ভয়ঙ্কর অনুশীলন। আপনার এটি করা উচিত নয় এবং আমি কেবল তার জন্য (যা আমি করিনি) তাকে
হ্রাস করা উচিত
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.