{"id":6436,"date":"2023-01-19T04:56:54","date_gmt":"2023-01-19T04:56:54","guid":{"rendered":"https:\/\/www.pythontutorial.net\/?page_id=6436"},"modified":"2023-01-19T06:49:33","modified_gmt":"2023-01-19T06:49:33","slug":"django-group-by","status":"publish","type":"page","link":"https:\/\/www.pythontutorial.net\/django-tutorial\/django-group-by\/","title":{"rendered":"Django Group By"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn how to use Django Group By with aggregate functions to calculate aggregation for groups.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='introduction-to-the-django-group-by'>Introduction to the Django Group By <a href=\"#introduction-to-the-django-group-by\" class=\"anchor\" id=\"introduction-to-the-django-group-by\" title=\"Anchor for Introduction to the Django Group By\">#<\/a><\/h2>\n\n\n\n<p>The SQL <a href=\"https:\/\/www.postgresqltutorial.com\/postgresql-tutorial\/postgresql-group-by\/\" target=\"_blank\" rel=\"noreferrer noopener\"><code>GROUP BY<\/code><\/a> clause groups the rows returned by a query into groups. Typically, you use <a href=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-aggregate\/\">aggregate functions<\/a> like count, min, max, avg, and sum with the <code>GROUP BY<\/code> clause to return an aggregated value for each group.<\/p>\n\n\n\n<p>Here&#8217;s the basic usage of the <code>GROUP<\/code> <code>BY<\/code> clause in a <code>SELECT<\/code> statement:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql\"><span class=\"hljs-keyword\">SELECT<\/span> column_1, <span class=\"hljs-keyword\">AGGREGATE<\/span>(column_2)\n<span class=\"hljs-keyword\">FROM<\/span> table_name\n<span class=\"hljs-keyword\">GROUP<\/span> <span class=\"hljs-keyword\">BY<\/span> column1;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In Django, you can you the <code>annotate()<\/code> method with the <code>values()<\/code> to apply the aggregation on groups like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">(Entity.objects\n    .values(<span class=\"hljs-string\">'column_2'<\/span>)\n    .annotate(value=AGGREGATE(<span class=\"hljs-string\">'column_1'<\/span>))\n)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this syntax;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>values('column_2')<\/code> &#8211; pass the column that you want to group to the <code>values()<\/code> method.<\/li>\n\n\n\n<li><code>annotate(value=AGGREGATE('column_1'))<\/code> &#8211; specify what to aggregate in the <code>annotate()<\/code> method.<\/li>\n<\/ul>\n\n\n\n<p>Notice that the order of calling <code>values()<\/code> and <code>annotates()<\/code> matter. If you do not call the <code>values()<\/code> method first and <code>annotate()<\/code> second, the expression won&#8217;t produce aggregate results.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='django-group-by-examples'>Django Group By examples <a href=\"#django-group-by-examples\" class=\"anchor\" id=\"django-group-by-examples\" title=\"Anchor for Django Group By examples\">#<\/a><\/h2>\n\n\n\n<p>We&#8217;ll use the Employee and Department models from the <code>HR<\/code> application for the demonstration. The <code>Emloyee<\/code> and <code>Department<\/code> models map to the <code>hr_employee<\/code> and <code>hr_department<\/code> tables in the database:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"374\" height=\"144\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2023\/01\/django_orm_employee_department.png\" alt=\"\" class=\"wp-image-6416\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2023\/01\/django_orm_employee_department.png 374w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2023\/01\/django_orm_employee_department-300x116.png 300w\" sizes=\"auto, (max-width: 374px) 100vw, 374px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id='1-django-group-by-with-count-example'>1) Django Group By with Count example <a href=\"#1-django-group-by-with-count-example\" class=\"anchor\" id=\"1-django-group-by-with-count-example\" title=\"Anchor for 1) Django Group By with Count example\">#<\/a><\/h3>\n\n\n\n<p>The following example uses the <code>values()<\/code> and <code>annotate()<\/code> method to get the number of employees by department:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>(Employee.objects\n<span class=\"hljs-meta\">... <\/span>    .values(<span class=\"hljs-string\">'department'<\/span>)\n<span class=\"hljs-meta\">... <\/span>    .annotate(head_count=Count(<span class=\"hljs-string\">'department'<\/span>))\n<span class=\"hljs-meta\">... <\/span>    .order_by(<span class=\"hljs-string\">'department'<\/span>)\n<span class=\"hljs-meta\">... <\/span> )\nSELECT <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>,\n       COUNT(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>) AS <span class=\"hljs-string\">\"head_count\"<\/span>\n  FROM <span class=\"hljs-string\">\"hr_employee\"<\/span>\n GROUP BY <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>\n ORDER BY <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span> ASC\n LIMIT <span class=\"hljs-number\">21<\/span>\nExecution time: <span class=\"hljs-number\">0.001492<\/span>s &#91;Database: default]\n&lt;QuerySet &#91;{<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">30<\/span>}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">2<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">40<\/span>}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">3<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">28<\/span>}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">4<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">29<\/span>}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">5<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">29<\/span>}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">6<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">30<\/span>}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">7<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">34<\/span>}]&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, group the employees by department using the <code>values()<\/code> method:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">values(<span class=\"hljs-string\">'department'<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, apply the <code>Count()<\/code> to each group:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">annotate(head_count=Count(<span class=\"hljs-string\">'department'<\/span>))<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, sort the objects in the <code>QuerySet<\/code> by department:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">order_by(<span class=\"hljs-string\">'department'<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Behind the scenes, Django executes the <code>SELECT<\/code> statement with the <code>GROUP<\/code> <code>BY<\/code> clause:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">SELECT<\/span> <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>,\n<\/span><\/span><mark class='shcb-loc'><span>       <span class=\"hljs-keyword\">COUNT<\/span>(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>) <span class=\"hljs-keyword\">AS<\/span> <span class=\"hljs-string\">\"head_count\"<\/span>\n<\/span><\/mark><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">FROM<\/span> <span class=\"hljs-string\">\"hr_employee\"<\/span>\n<\/span><\/span><mark class='shcb-loc'><span> <span class=\"hljs-keyword\">GROUP<\/span> <span class=\"hljs-keyword\">BY<\/span> <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>\n<\/span><\/mark><span class='shcb-loc'><span> <span class=\"hljs-keyword\">ORDER<\/span> <span class=\"hljs-keyword\">BY<\/span> <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span> <span class=\"hljs-keyword\">ASC<\/span>\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">LIMIT<\/span> <span class=\"hljs-number\">21<\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='2-django-group-by-with-sum-example'>2) Django Group By with Sum example <a href=\"#2-django-group-by-with-sum-example\" class=\"anchor\" id=\"2-django-group-by-with-sum-example\" title=\"Anchor for 2) Django Group By with Sum example\">#<\/a><\/h3>\n\n\n\n<p>Similarly, you can use the <code>Sum()<\/code> aggregate to calculate the total salary of employees in each department:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>(Employee.objects\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span>    .values(<span class=\"hljs-string\">'department'<\/span>)\n<\/span><\/span><mark class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span>    .annotate(total_salary=Sum(<span class=\"hljs-string\">'salary'<\/span>))\n<\/span><\/mark><span class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span>    .order_by(<span class=\"hljs-string\">'department'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span> )\n<\/span><\/span><span class='shcb-loc'><span>SELECT <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>,\n<\/span><\/span><mark class='shcb-loc'><span>       SUM(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"salary\"<\/span>) AS <span class=\"hljs-string\">\"total_salary\"<\/span>\n<\/span><\/mark><span class='shcb-loc'><span>  FROM <span class=\"hljs-string\">\"hr_employee\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span> GROUP BY <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span> ORDER BY <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span> ASC\n<\/span><\/span><span class='shcb-loc'><span> LIMIT <span class=\"hljs-number\">21<\/span>\n<\/span><\/span><span class='shcb-loc'><span>Execution time: <span class=\"hljs-number\">0.000927<\/span>s &#91;Database: default]\n<\/span><\/span><span class='shcb-loc'><span>&lt;QuerySet &#91;{<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-string\">'total_salary'<\/span>: Decimal(<span class=\"hljs-string\">'3615341.00'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">2<\/span>, <span class=\"hljs-string\">'total_salary'<\/span>: Decimal(<span class=\"hljs-string\">'5141611.00'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">3<\/span>, <span class=\"hljs-string\">'total_salary'<\/span>: Decimal(<span class=\"hljs-string\">'3728988.00'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">4<\/span>, <span class=\"hljs-string\">'total_salary'<\/span>: Decimal(<span class=\"hljs-string\">'3955669.00'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">5<\/span>, <span class=\"hljs-string\">'total_salary'<\/span>: Decimal(<span class=\"hljs-string\">'4385784.00'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">6<\/span>, <span class=\"hljs-string\">'total_salary'<\/span>: Decimal(<span class=\"hljs-string\">'4735927.00'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">7<\/span>, <span class=\"hljs-string\">'total_salary'<\/span>: Decimal(<span class=\"hljs-string\">'4598788.00'<\/span>)}]&gt;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='3-django-group-by-with-min-max-and-avg-example'>3) Django Group By with Min, Max, and Avg example <a href=\"#3-django-group-by-with-min-max-and-avg-example\" class=\"anchor\" id=\"3-django-group-by-with-min-max-and-avg-example\" title=\"Anchor for 3) Django Group By with Min, Max, and Avg example\">#<\/a><\/h3>\n\n\n\n<p>The following example applies multiple aggregate functions to groups to get the lowest, average, and highest salary of employees in each department:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>(Employee.objects\n<span class=\"hljs-meta\">... <\/span>    .values(<span class=\"hljs-string\">'department'<\/span>)\n<span class=\"hljs-meta\">... <\/span>    .annotate(\n<span class=\"hljs-meta\">... <\/span>        min_salary=Min(<span class=\"hljs-string\">'salary'<\/span>),\n<span class=\"hljs-meta\">... <\/span>        max_salary=Max(<span class=\"hljs-string\">'salary'<\/span>),\n<span class=\"hljs-meta\">... <\/span>        avg_salary=Avg(<span class=\"hljs-string\">'salary'<\/span>)\n<span class=\"hljs-meta\">... <\/span>    )\n<span class=\"hljs-meta\">... <\/span>    .order_by(<span class=\"hljs-string\">'department'<\/span>)\n<span class=\"hljs-meta\">... <\/span> )\nSELECT <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>,\n       MIN(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"salary\"<\/span>) AS <span class=\"hljs-string\">\"min_salary\"<\/span>,\n       MAX(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"salary\"<\/span>) AS <span class=\"hljs-string\">\"max_salary\"<\/span>,\n       AVG(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"salary\"<\/span>) AS <span class=\"hljs-string\">\"avg_salary\"<\/span>\n  FROM <span class=\"hljs-string\">\"hr_employee\"<\/span>\n GROUP BY <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>\n ORDER BY <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span> ASC\n LIMIT <span class=\"hljs-number\">21<\/span>\nExecution time: <span class=\"hljs-number\">0.001670<\/span>s &#91;Database: default]\n&lt;QuerySet &#91;{<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-string\">'min_salary'<\/span>: Decimal(<span class=\"hljs-string\">'45427.00'<\/span>), <span class=\"hljs-string\">'max_salary'<\/span>: Decimal(<span class=\"hljs-string\">'149830.00'<\/span>), <span class=\"hljs-string\">'avg_salary'<\/span>: Decimal(<span class=\"hljs-string\">'120511.366666666667'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: \n<span class=\"hljs-number\">2<\/span>, <span class=\"hljs-string\">'min_salary'<\/span>: Decimal(<span class=\"hljs-string\">'46637.00'<\/span>), <span class=\"hljs-string\">'max_salary'<\/span>: Decimal(<span class=\"hljs-string\">'243462.00'<\/span>), <span class=\"hljs-string\">'avg_salary'<\/span>: Decimal(<span class=\"hljs-string\">'128540.275000000000'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">3<\/span>, <span class=\"hljs-string\">'min_salary'<\/span>: Decimal(<span class=\"hljs-string\">'40762.00'<\/span>), <span class=\"hljs-string\">'max_salary'<\/span>: Decimal(<span class=\"hljs-string\">'248265.00'<\/span>), <span class=\"hljs-string\">'avg_salary'<\/span>: Decimal(<span class=\"hljs-string\">'133178.142857142857'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">4<\/span>, <span class=\"hljs-string\">'min_salary'<\/span>: Decimal(<span class=\"hljs-string\">'43000.00'<\/span>), <span class=\"hljs-string\">'max_salary'<\/span>: \nDecimal(<span class=\"hljs-string\">'238016.00'<\/span>), <span class=\"hljs-string\">'avg_salary'<\/span>: Decimal(<span class=\"hljs-string\">'136402.379310344828'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">5<\/span>, <span class=\"hljs-string\">'min_salary'<\/span>: Decimal(<span class=\"hljs-string\">'42080.00'<\/span>), <span class=\"hljs-string\">'max_salary'<\/span>: Decimal(<span class=\"hljs-string\">'246403.00'<\/span>), <span class=\"hljs-string\">'avg_salary'<\/span>: Decimal(<span class=\"hljs-string\">'151233.931034482759'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">6<\/span>, <span class=\"hljs-string\">'min_salary'<\/span>: Decimal(<span class=\"hljs-string\">'58356.00'<\/span>), <span class=\"hljs-string\">'max_salary'<\/span>: Decimal(<span class=\"hljs-string\">'248312.00'<\/span>), <span class=\"hljs-string\">'avg_salary'<\/span>: Decimal(<span class=\"hljs-string\">'157864.233333333333'<\/span>)}, {<span class=\"hljs-string\">'department'<\/span>: <span class=\"hljs-number\">7<\/span>, <span class=\"hljs-string\">'min_salary'<\/span>: Decimal(<span class=\"hljs-string\">'40543.00'<\/span>), <span class=\"hljs-string\">'max_salary'<\/span>: Decimal(<span class=\"hljs-string\">'238892.00'<\/span>), <span class=\"hljs-string\">'avg_salary'<\/span>: Decimal(<span class=\"hljs-string\">'135258.470588235294'<\/span>)}]&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='4-django-group-by-with-join-example'>4) Django group by with join example <a href=\"#4-django-group-by-with-join-example\" class=\"anchor\" id=\"4-django-group-by-with-join-example\" title=\"Anchor for 4) Django group by with join example\">#<\/a><\/h3>\n\n\n\n<p>The following example uses the <code>values()<\/code> and <code>annotate()<\/code> methods to get the number of employees per department:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>(Department.objects\n<span class=\"hljs-meta\">... <\/span>    .values(<span class=\"hljs-string\">'name'<\/span>)\n<span class=\"hljs-meta\">... <\/span>    .annotate(\n<span class=\"hljs-meta\">... <\/span>        head_count=Count(<span class=\"hljs-string\">'employee'<\/span>)\n<span class=\"hljs-meta\">... <\/span>    )\n<span class=\"hljs-meta\">... <\/span> )\nSELECT <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"name\"<\/span>,\n       COUNT(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>) AS <span class=\"hljs-string\">\"head_count\"<\/span>\n  FROM <span class=\"hljs-string\">\"hr_department\"<\/span>\n  LEFT OUTER JOIN <span class=\"hljs-string\">\"hr_employee\"<\/span>\n    ON (<span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span> = <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>)\n GROUP BY <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"name\"<\/span>\n LIMIT <span class=\"hljs-number\">21<\/span>\nExecution time: <span class=\"hljs-number\">0.001953<\/span>s &#91;Database: default]\n&lt;QuerySet &#91;{<span class=\"hljs-string\">'name'<\/span>: <span class=\"hljs-string\">'Marketing'<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">28<\/span>}, {<span class=\"hljs-string\">'name'<\/span>: <span class=\"hljs-string\">'Finance'<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">29<\/span>}, {<span class=\"hljs-string\">'name'<\/span>: <span class=\"hljs-string\">'SCM'<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">29<\/span>}, {<span class=\"hljs-string\">'name'<\/span>: <span class=\"hljs-string\">'GA'<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">30<\/span>}, {<span class=\"hljs-string\">'name'<\/span>: <span class=\"hljs-string\">'Sales'<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">40<\/span>}, {<span class=\"hljs-string\">'name'<\/span>: <span class=\"hljs-string\">'IT'<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">30<\/span>}, {<span class=\"hljs-string\">'name'<\/span>: <span class=\"hljs-string\">'HR'<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">34<\/span>}]&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>values('name')<\/code>  &#8211; groups department by name.<\/li>\n\n\n\n<li><code>annotate(headcount=Count('employee'))<\/code> &#8211; counts employees in each department.<\/li>\n<\/ul>\n\n\n\n<p>Behind the scenes, Django uses a <code>LEFT<\/code> <code>JOIN<\/code> to join the <code>hr_department<\/code> table with <code>hr_employee<\/code> table and apply the <code>COUNT()<\/code> function to each group.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='django-group-by-with-having'>Django group by with having <a href=\"#django-group-by-with-having\" class=\"anchor\" id=\"django-group-by-with-having\" title=\"Anchor for Django group by with having\">#<\/a><\/h2>\n\n\n\n<p>To apply a condition to the groups, you use the <code>filter()<\/code> method. For example, the following uses the <code>filter()<\/code> method to get the department with head counts are more than 30:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>(Department.objects\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span>    .values(<span class=\"hljs-string\">'name'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span>    .annotate(\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span>        head_count=Count(<span class=\"hljs-string\">'employee'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span>    )\n<\/span><\/span><mark class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span>    .filter(head_count__gt=<span class=\"hljs-number\">30<\/span>)\n<\/span><\/mark><span class='shcb-loc'><span><span class=\"hljs-meta\">... <\/span> )\n<\/span><\/span><span class='shcb-loc'><span>SELECT <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"name\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>       COUNT(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>) AS <span class=\"hljs-string\">\"head_count\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  FROM <span class=\"hljs-string\">\"hr_department\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  LEFT OUTER JOIN <span class=\"hljs-string\">\"hr_employee\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    ON (<span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span> = <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>)\n<\/span><\/span><span class='shcb-loc'><span> GROUP BY <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"name\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span>HAVING COUNT(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>) &gt; <span class=\"hljs-number\">30<\/span>\n<\/span><\/span><span class='shcb-loc'><span> LIMIT <span class=\"hljs-number\">21<\/span>\n<\/span><\/span><span class='shcb-loc'><span>Execution time: <span class=\"hljs-number\">0.002893<\/span>s &#91;Database: default]\n<\/span><\/span><span class='shcb-loc'><span>&lt;QuerySet &#91;{<span class=\"hljs-string\">'name'<\/span>: <span class=\"hljs-string\">'Sales'<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">40<\/span>}, {<span class=\"hljs-string\">'name'<\/span>: <span class=\"hljs-string\">'HR'<\/span>, <span class=\"hljs-string\">'head_count'<\/span>: <span class=\"hljs-number\">34<\/span>}]&gt;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Behind the scenes, Django uses the <code>HAVING<\/code> clause to filter the group based on the condition that we pass to the <code>filter()<\/code> method:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-code-table\"><span class='shcb-loc'><span>SELECT <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"name\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>       COUNT(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>) AS <span class=\"hljs-string\">\"head_count\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  FROM <span class=\"hljs-string\">\"hr_department\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  LEFT OUTER JOIN <span class=\"hljs-string\">\"hr_employee\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    ON (<span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span> = <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>)\n<\/span><\/span><span class='shcb-loc'><span> GROUP BY <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"name\"<\/span>\n<\/span><\/span><mark class='shcb-loc'><span>HAVING COUNT(<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>) &gt; <span class=\"hljs-number\">30<\/span>\n<\/span><\/mark><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='summary'>Summary <a href=\"#summary\" class=\"anchor\" id=\"summary\" title=\"Anchor for Summary\">#<\/a><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <code>values()<\/code> and <code>annotate()<\/code> method to group rows into groups.<\/li>\n\n\n\n<li>Use <code>filter()<\/code> to add conditions to filter groups.<\/li>\n<\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Was this tutorial helpful ?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"6436\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-group-by\/\"\n\t\t\t\tdata-post-title=\"Django Group By\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"6436\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-group-by\/\"\n\t\t\t\tdata-post-title=\"Django Group By\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\t\t\t<input type=\"button\" name=\"wth-submit\" class=\"wth-btn wth-btn-submit\" id=\"wth-submit\" \/>\n\t\t\t<input type=\"button\" class=\"wth-btn wth-btn-cancel\" value=\"Cancel\" \/>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you&#8217;ll learn how to use Django Group By with aggregate functions to calculate aggregation for groups.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":5531,"menu_order":36,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-6436","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/6436","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/comments?post=6436"}],"version-history":[{"count":0,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/6436\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/5531"}],"wp:attachment":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/media?parent=6436"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}