2010-09-26 8 views
8

मैं है Django मॉडल का अनुसरण (टेबल 'ए' को मैप किया):Django क्वेरी - "मामला है जब" एकत्रीकरण समारोह के साथ

select avg(case 
     when (value > 0 and value <= 50) then 0 
     when (value > 50 and value < 70) then 50 
     else 100 end) 
from A 
where ... 
:

class A(models.Model): 
    name = models.CharField(max_length=64, null=False) 
    value = models.IntegerField() 
    ... 

मैं शीर्ष पर निम्नलिखित सरल क्वेरी निष्पादित करना चाहते हैं

मैं कच्चे एसक्यूएल से बचने की कोशिश कर रहा हूं - इसे डीजेंगो के साथ कैसे कार्यान्वित किया जा सकता है (उपर्युक्त उदाहरण में मैं औसत का उपयोग कर रहा हूं, लेकिन वही प्रश्न अधिकतम, न्यूनतम, योग आदि के लिए भी प्रासंगिक है)?

मैं अतिरिक्त और कुल उपयोग करने की कोशिश:

extra(select={'avg_field': case_when_query}) 

और

aggregate(Avg('avg_field')), 

लेकिन इतना अतिरिक्त क्षेत्र यहाँ नहीं किया जा सकता समेकित फ़ंक्शन केवल मॉडल क्षेत्रों के साथ काम करता है। यह django के साथ कैसे किया जा सकता है?

मदद

के लिए धन्यवाद

उत्तर

2

किया जा सकता है क्या है कि अभी भी हमें Django क्वेरीसमूह का उपयोग करने की अनुमति देगा कुछ इस तरह है:

qs = A.objects.extra(select={"avg_field": 
        "avg(case when...)"}).filter(...).values("avg_field") 

परिणाम का उपयोग करें:

qs[0]["avg_field"] 

और यह जरूरत की अनुमति होगी कार्यक्षमता।

2

जहाँ तक मुझे पता के रूप में वहाँ है (दुर्भाग्य से) कोई क्या आप कच्चे एसक्यूएल का सहारा के बिना वर्णित करने के लिए जिस तरह से।

ने कहा कि औसत वर्णन की गणना करने का एक तरीका है यदि आप अपने डेटा को थोड़ा सा डिमॉर्मलाइज करना चाहते हैं। उदाहरण के लिए आप average_field नामक एक नया कॉलम जोड़ सकते हैं जो save() पर उचित मान पर स्वचालित रूप से सेट हो जाता है। आप या तो save() ओवरराइड कर सकते हैं या स्वचालित रूप से ऐसा करने के लिए सिग्नल टैप कर सकते हैं। उदाहरण के लिए

class A(models.Model): 
    name = models.CharField(max_length=64, null=False) 
    value = models.IntegerField() 
    average_field = models.IntegerField(default = 0) 

    def _get_average_field(self): 
     # Trying to match the case statement's syntax. 
     # You can also do 0 < self.value <= 50 
     if self.value > 0 and self.value <= 50: 
      return 0 
     elif self.value > 50 and self.value < 70: 
      return 50 
     else: 
      return 100 

    def save(self, *args, **kwargs): 
     if self.value: 
      self.average_field = self._get_average_field() 
     super(A, self).save(*args, **kwargs) 

एक बार ऐसा करने के बाद आपकी क्वेरीिंग बहुत आसान हो जाती है।

A.objects.filter(...).aggregate(avg = Avg('average_field')) 
+0

धन्यवाद। दुर्भाग्य से मैं इन मानों को डेटाबेस तालिका में संग्रहीत नहीं कर सकता क्योंकि "केस जब" मान गणना के आधार पर अलग-अलग हो सकता है जो मैं करना चाहता हूं। – Lin

+0

@ एलआई: समझा। मैं देख सकता हूं कि यह उस मामले में क्यों काम नहीं करेगा। –

+0

मदद के लिए फिर से धन्यवाद। आखिर में अतिरिक्त + मूल्यों का उपयोग करके मुझे वह परिणाम मिला जो मैं चाहता था। – Lin

संबंधित मुद्दे