|
1 | 1 | from unittest import TestCase |
2 | 2 |
|
3 | 3 | from piccolo.apps.user.tables import BaseUser |
| 4 | +from piccolo.query.methods.select import Count |
4 | 5 |
|
5 | 6 | from ..base import DBTestCase, postgres_only, sqlite_only |
6 | 7 | from ..example_project.tables import Band, Concert |
@@ -293,6 +294,91 @@ def test_distinct(self): |
293 | 294 |
|
294 | 295 | self.assertTrue(response == [{"name": "Pythonistas"}]) |
295 | 296 |
|
| 297 | + def test_count_group_by(self): |
| 298 | + """ |
| 299 | + Test grouping and counting all rows. |
| 300 | + """ |
| 301 | + self.insert_rows() |
| 302 | + self.insert_rows() |
| 303 | + |
| 304 | + response = ( |
| 305 | + Band.select(Band.name, Count()) |
| 306 | + .group_by(Band.name) |
| 307 | + .order_by(Band.name) |
| 308 | + .run_sync() |
| 309 | + ) |
| 310 | + |
| 311 | + self.assertTrue( |
| 312 | + response |
| 313 | + == [ |
| 314 | + {"name": "CSharps", "count": 2}, |
| 315 | + {"name": "Pythonistas", "count": 2}, |
| 316 | + {"name": "Rustaceans", "count": 2}, |
| 317 | + ] |
| 318 | + ) |
| 319 | + |
| 320 | + def test_count_column_group_by(self): |
| 321 | + """ |
| 322 | + Test grouping and counting a specific column. Any null values in the |
| 323 | + specified column will be omitted from the count. |
| 324 | + """ |
| 325 | + self.insert_rows() |
| 326 | + self.insert_rows() |
| 327 | + self.run_sync( |
| 328 | + """ |
| 329 | + INSERT INTO band ( |
| 330 | + name, |
| 331 | + manager, |
| 332 | + popularity |
| 333 | + ) VALUES ( |
| 334 | + 'SomeBand', |
| 335 | + null, |
| 336 | + 1000 |
| 337 | + );""" |
| 338 | + ) |
| 339 | + |
| 340 | + response = ( |
| 341 | + Band.select(Band.manager.name, Count(Band.manager)) |
| 342 | + .group_by(Band.manager.name) |
| 343 | + .order_by(Band.manager.name) |
| 344 | + .run_sync() |
| 345 | + ) |
| 346 | + |
| 347 | + # We need to sort them, because SQLite and Postgres treat Null |
| 348 | + # differently when sorting. |
| 349 | + response = sorted(response, key=lambda x: x["manager.name"] or "") |
| 350 | + |
| 351 | + self.assertTrue( |
| 352 | + response |
| 353 | + == [ |
| 354 | + {"manager.name": None, "count": 0}, |
| 355 | + {"manager.name": "Graydon", "count": 2}, |
| 356 | + {"manager.name": "Guido", "count": 2}, |
| 357 | + {"manager.name": "Mads", "count": 2}, |
| 358 | + ] |
| 359 | + ) |
| 360 | + |
| 361 | + # This time the nulls should be counted, as we omit the column argument |
| 362 | + # from Count: |
| 363 | + response = ( |
| 364 | + Band.select(Band.manager.name, Count()) |
| 365 | + .group_by(Band.manager.name) |
| 366 | + .order_by(Band.manager.name) |
| 367 | + .run_sync() |
| 368 | + ) |
| 369 | + |
| 370 | + response = sorted(response, key=lambda x: x["manager.name"] or "") |
| 371 | + |
| 372 | + self.assertTrue( |
| 373 | + response |
| 374 | + == [ |
| 375 | + {"manager.name": None, "count": 1}, |
| 376 | + {"manager.name": "Graydon", "count": 2}, |
| 377 | + {"manager.name": "Guido", "count": 2}, |
| 378 | + {"manager.name": "Mads", "count": 2}, |
| 379 | + ] |
| 380 | + ) |
| 381 | + |
296 | 382 | def test_columns(self): |
297 | 383 | """ |
298 | 384 | Make sure the colums method can be used to specify which columns to |
|
0 commit comments