Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group and count with condition

Tags:

I'm trying to group a set of documents and count them based on their value:

{ item: "abc1", value: 1 } { item: "abc1", value: 1 } { item: "abc1", value: 11 } { item: "xyz1", value: 2 } 

I would like to group by item and get in return a count of how many times the value is bigger than 10 and how many times smaller:

{ item: "abc1", countSmaller: 2, countBigger: 1 } { item: "xyz1", countSmaller: 1, countBigger: 0 } 
like image 487
maephisto Avatar asked May 11 '15 13:05

maephisto


People also ask

Can we use count and GROUP BY together?

The use of COUNT() function in conjunction with GROUP BY is useful for characterizing our data under various groupings. A combination of same values (on a column) will be treated as an individual group.

How do you use count in GROUP BY clause?

SQL – count() with Group By clause The count() function is an aggregate function use to find the count of the rows that satisfy the fixed conditions. The count() function with the GROUP BY clause is used to count the data which were grouped on a particular attribute of the table.

Can we use GROUP BY and count together in SQL?

We can use GROUP BY to group together rows that have the same value in the Animal column, while using COUNT() to find out how many ID's we have in each group. It returns a table with three rows (one for each distinct animal).

Can I put condition in count in SQL?

COUNT() with HAVINGThe HAVING clause with SQL COUNT() function can be used to set a condition with the select statement. The HAVING clause is used instead of WHERE clause with SQL COUNT() function.


2 Answers

What you need is the $cond operator of aggregation framework. One way to get what you want would be:

db.foo.aggregate([     {         $project: {             item: 1,             lessThan10: {  // Set to 1 if value < 10                 $cond: [ { $lt: ["$value", 10 ] }, 1, 0]             },             moreThan10: {  // Set to 1 if value > 10                 $cond: [ { $gt: [ "$value", 10 ] }, 1, 0]             }         }     },     {         $group: {             _id: "$item",             countSmaller: { $sum: "$lessThan10" },             countBigger: { $sum: "$moreThan10" }         }     } ]) 

Note: I have assumed value to numeric rather than String.

Output:

{         "result" : [                 {                         "_id" : "xyz1",                         "countSmaller" : 1,                         "countBigger" : 0                 },                 {                         "_id" : "abc1",                         "countSmaller" : 2,                         "countBigger" : 2                 }         ],         "ok" : 1 }   
like image 147
Anand Jayabalan Avatar answered Oct 21 '22 01:10

Anand Jayabalan


You need to use the $cond operator. Here 0 is value less than 10 and 1 value greater than 10. This doesn't exactly give you expected output. Perhaps someone will post better answer.

db.collection.aggregate(     [         {             "$project":                  {                     "item": 1,                      "value":                          {                             "$cond": [ { "$gt": [ "$value", 10 ] }, 1, 0 ]                          }                  }          },           {              "$group":                   {                      "_id": { "item": "$item", "value": "$value" },                                             "count": { "$sum": 1 }                  }          },           {              "$group":                   {                       "_id": "$_id.item",                       "stat": { "$push": { "value": "$_id.value", "count": "$count" }}                  }           }     ] ) 

Output:

{         "_id" : "abc1",         "stat" : [                 {                         "value" : 1,                         "count" : 2                 },                 {                         "value" : 0,                         "count" : 2                 }         ] } { "_id" : "xyz1", "stat" : [ { "value" : 0, "count" : 1 } ] } 

You will need to convert your value to integer or float

like image 36
styvane Avatar answered Oct 20 '22 23:10

styvane