2012-02-26 34 views
7

Trong mô hình Django của tôi, tôi đã có một mô hình rất đơn giản mà đại diện cho một lần xuất hiện của một sự kiện (chẳng hạn như một cảnh báo máy chủ xảy ra):Nhóm theo tuần, và đệm ra 'mất tích' tuần

class EventOccurrence: 
    event = models.ForeignKey(Event) 
    time = models.DateTimeField() 

Mục tiêu cuối cùng của tôi là tạo bảng hoặc biểu đồ hiển thị số lần một sự kiện đã xảy ra trong n trước đây tuần qua.

Vì vậy, câu hỏi của tôi có hai phần:

  • Làm thế nào tôi có thể group_by tuần của trường time?
  • Tôi làm cách nào để "kết thúc" kết quả của group_by này để thêm giá trị bằng 0 cho bất kỳ tuần bị thiếu nào?

Ví dụ, đối với phần thứ hai, tôi muốn chuyển đổi một kết quả như thế này:

| week | count |     | week | count | 
| 2 | 3  |     | 2 | 3  | 
| 3 | 5  | —— becomes —> | 3 | 5  | 
| 5 | 1  |     | 4 | 0  | 
            | 5 | 1  | 

cách tốt nhất để làm điều này trong Django là gì? Các giải pháp chung của Python cũng OK.

Trả lời

4

của Django DateField cũng như datetime không hỗ trợ thuộc tính tuần. Để tìm nạp mọi thứ trong một truy vấn bạn cần làm:

from django.db import connection 

cursor = connection.cursor() 
cursor.execute(" SELECT WEEK(`time`) AS 'week', COUNT(*) AS 'count' FROM %s GROUP BY WEEK(`time`) ORDER BY WEEK(`time`)" % EventOccurrence._meta.db_table, []) 

data = [] 
results = cursor.fetchall() 
for i, row in enumerate(results[:-1]): 
    data.append(row) 

    week = row[0] + 1 
    next_week = results[i+1][0] 
    while week < next_week: 
     data.append((week, 0)) 
     week += 1 
data.append(results[-1]) 

print data 
0

Sau khi đào truy vấn tài liệu truy vấn django, tôi không tìm thấy cách để thực hiện truy vấn thông qua hệ thống ORM django. Cursor là một cách giải quyết, nếu thương hiệu cơ sở dữ liệu của bạn là MySQL:

from django.db import connection, transaction 
cursor = connection.cursor() 

cursor.execute(""" 
    select 
     week(time) as `week`, 
     count(*) as `count` 
    from EventOccurrence 
    group by week(time) 
    order by 1;""") 

myData = dictfetchall(cursor) 

Đây là, theo ý kiến ​​của tôi, giải pháp hiệu quả tốt nhất. Nhưng lưu ý rằng điều này không thiếu tuần mất tích.

EDITED giải pháp cơ sở dữ liệu thương hiệu việc độc lập qua python (hiệu suất ít hơn)

Nếu bạn đang tìm kiếm cho mã độc lập cơ sở dữ liệu thương hiệu thì bạn nên lấy số ngày từng ngày và tổng hợp nó qua python. Nếu đây là mã trường hợp của bạn có thể trông giống như:

#get all weeks: 
import datetime 
weeks = set() 
d7 = datetime.timedelta(days = 7) 
iterDay = datetime.date(2012,1,1) 
while iterDay <= datetime.now(): 
    weeks.add(iterDay.isocalendar()[1]) 
    iterDay += d7 

#get all events 
allEvents = EventOccurrence.objects.value_list('time', flat=True) 

#aggregate event by week 
result = dict() 
for w in weeks: 
    result.setdefault(w ,0) 

for e in allEvents: 
    result[ e.isocalendar()[1] ] += 1 

(Disclaimer: không kiểm tra)

0

Vì tôi phải truy vấn nhiều bảng bằng cách tham gia, tôi đang sử dụng chế độ xem db để giải quyết các yêu cầu này.

CREATE VIEW my_view 
    AS 
    SELECT 
    *, // <-- other fields goes here 
    YEAR(time_field) as year, 
    WEEK(time_field) as week 
    FROM my_table; 

và mô hình như:

from django.db import models 

class MyView(models.Model): 
    # other fields goes here 
    year = models.IntegerField() 
    week = models.IntegerField() 

    class Meta: 
     managed = False 
     db_table = 'my_view' 

    def query(): 
     rows = MyView.objects.filter(week__range=[2, 5]) 
     # to handle the rows 

sau khi nhận được hàng từ cái nhìn db này, sử dụng đường bởi @danihp để đệm 0 cho "lỗ" tuần/tháng.

LƯU Ý: điều này chỉ được thử nghiệm cho chương trình phụ trợ của MySQL, tôi không chắc liệu nó có OK cho MS SQL Server hay không.

Các vấn đề liên quan