Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

OuterRef . के साथ सरल सबक्वेरी

आपके उदाहरण के साथ एक समस्या यह है कि आप queryset.count() . का उपयोग नहीं कर सकते हैं एक सबक्वेरी के रूप में, क्योंकि .count() क्वेरीसेट का मूल्यांकन करने और गिनती वापस करने का प्रयास करता है।

तो कोई सोच सकता है कि Count() . का उपयोग करना सही तरीका होगा बजाय। शायद कुछ ऐसा:

Post.objects.annotate(
    count=Count(Tag.objects.filter(post=OuterRef('pk')))
)

यह दो कारणों से काम नहीं करेगा:

  1. Tag क्वेरीसेट सभी Tag . का चयन करता है फ़ील्ड, जबकि Count केवल एक क्षेत्र पर भरोसा कर सकते हैं। इस प्रकार:Tag.objects.filter(post=OuterRef('pk')).only('pk') की आवश्यकता है (tag.pk पर गिनती का चयन करने के लिए )।

  2. Count स्वयं एक Subquery नहीं है वर्ग, Count एक Aggregate है . तो Count . द्वारा उत्पन्न व्यंजक Subquery के रूप में मान्यता प्राप्त नहीं है (OuterRef सबक्वेरी की आवश्यकता है), हम Subquery . का उपयोग करके इसे ठीक कर सकते हैं ।

1) और 2) के लिए सुधार लागू करने से निम्नलिखित परिणाम प्राप्त होंगे:

Post.objects.annotate(
    count=Count(Subquery(Tag.objects.filter(post=OuterRef('pk')).only('pk')))
)

हालांकि यदि आप तैयार की जा रही क्वेरी का निरीक्षण करते हैं:

SELECT 
    "tests_post"."id",
    "tests_post"."title",
    COUNT((SELECT U0."id" 
            FROM "tests_tag" U0 
            INNER JOIN "tests_post_tags" U1 ON (U0."id" = U1."tag_id") 
            WHERE U1."post_id" = ("tests_post"."id"))
    ) AS "count" 
FROM "tests_post" 
GROUP BY 
    "tests_post"."id",
    "tests_post"."title"

आपको एक GROUP BY दिखाई देगा खंड। ऐसा इसलिए है क्योंकि COUNT एक समग्र कार्य है। अभी यह परिणाम को प्रभावित नहीं करता है, लेकिन कुछ अन्य मामलों में यह हो सकता है। इसीलिए दस्तावेज़ एक अलग दृष्टिकोण का सुझाव दें, जहां एकत्रीकरण को subquery . में ले जाया जाता है values . के विशिष्ट संयोजन के माध्यम से + annotate + values :

Post.objects.annotate(
    count=Subquery(
        Tag.objects
            .filter(post=OuterRef('pk'))
            # The first .values call defines our GROUP BY clause
            # Its important to have a filtration on every field defined here
            # Otherwise you will have more than one group per row!!!
            # This will lead to subqueries to return more than one row!
            # But they are not allowed to do that!
            # In our example we group only by post
            # and we filter by post via OuterRef
            .values('post')
            # Here we say: count how many rows we have per group 
            .annotate(count=Count('pk'))
            # Here we say: return only the count
            .values('count')
    )
)

अंत में यह उत्पादन करेगा:

SELECT 
    "tests_post"."id",
    "tests_post"."title",
    (SELECT COUNT(U0."id") AS "count" 
            FROM "tests_tag" U0 
            INNER JOIN "tests_post_tags" U1 ON (U0."id" = U1."tag_id") 
            WHERE U1."post_id" = ("tests_post"."id") 
            GROUP BY U1."post_id"
    ) AS "count" 
FROM "tests_post"


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. पंक्तियों की निश्चित संख्या के साथ MySQL तालिका?

  2. क्या मैं एक JDBC तैयार क्वेरी में एक से अधिक कथनों का उपयोग कर सकता हूँ?

  3. MySQL डेटाबेस में खोजते समय '%' चिह्न का मिलान करें

  4. MySQL - इकाई:तालिका 'TableDetails' में कॉलम 'IsPrimaryKey' के लिए मान DBNull है

  5. PHP का उपयोग करके MySQL समय को UNIX टाइमस्टैम्प में कैसे बदलें?